SpringBoot 与 消息队列——以RabbitMQ为例

最近在分模块的学习SpringBoot,目前将已经学习的模块代码已上传至github,欢迎参考、学习、指导。

一、概述

(1)大多数应用中,可通过消息服务中间件来提升系统异步通信、扩展解耦的能力。
在这里插入图片描述上图中第一个:用户在注册时,需要向用户发送注册成功的邮件以及短信。采用图一的传统同步的方式,比较耗时。
上图中第二个:为了解决图一的问题,在发送邮件和短信的时候,可以采用多线程的方法,以节省用户等待的时间。
上图中第三个:采用消息中间件的方式,将发送邮件和短信写入消息队列,然后立刻返回给用户,不用等发送邮件和短信结束后返回,减少了用户的等待时间,后台采用异步的方式从消息队列中读取执行相应的操作。

(2)消息服务中两个重要的概念
消息代理:当消息发送者发送消息以后,将由消息代理接管
目的地:消息代理保证消息传递到指定的目的地,消息队列主要由两种形式的目的地:

  • 队列:点对点消息通信
  • 主题:发布/订阅消息通信

(3)两个常见的消息服务规范

  • JMS(Java Message Service):Java消息服务——基于JVM消息代理的规范。ActiveMQ、HornetMQ是JMS的实现。
  • AMQP(Advanced Message Queuing Protocol):高级消息队列协议,也是一个消息代理规范,兼容JMS。RabbitMQ是AMQP的实现。

二、RabbitMQ

是AMQP的开源实现

1、核心概念

  • Message :消息,由消息头和消息体组成。消息体是不透明的,而消息头由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对与其他消息的优先权)等等。
  • Publisher:消息的生产者,向交换器发布消息的客户端应用程序。
  • Consumer: 消息的消费者。从消息队列中取得消息的客户端应用程序。
  • Exchange: 交换器,用来接收生产者发送的消息并将这些消息路由到服务器中的队列。服务器中可能由多个消息队列。通过消息中的路由键发送到指定的消息队列。
  • Queue: 消息队列,用来保存消息直到发送给消费者。是消息的容器也是消息的终点。一个消息可以投入到一个或多个队列。
  • Binding: 绑定,用于消息队列和交换器之间的关联。Exchange 和 Queue的绑定可以是多对多的关系。
  • Channel: 信道,多路复用连接中一条独立的双向数据流通道。信道是简历在真实的TCP连接内的虚拟连接。AMQP命令都是通过信道发送出去的。不管是发布消息、订阅消息还是接收消息,这些动作都是通过信道完成的。因为对操作系统来说建立和销毁TCP都是非常昂贵的开销。所以引入了信道的概念,以复用一条TCP连接。
  • Broker:表示消息队列服务器实体
    在这里插入图片描述

2、运行机制

运行机制其实就是核心概念中的那幅图,通过交换器将消息存放到消息队列中。Exchange分发消息时根据类型的不同分发策略也不同看,目前共有四种类型。

  • direct:直连健,消息的路由键和对列的键一致时,就会将该消息存放到相应的消息队列中,也就是之前说的点对点模式。
    在这里插入图片描述
  • Fanout:每个发到Fanout类型交换器上的消息都会分到所有绑定的队列上去。Fanout不处理路由键,发送消息最快。也就是之前说的广播模式。
    在这里插入图片描述
  • Topic:可以通过模式匹配分配消息的路由键属性。
    在这里插入图片描述
  • Headers:headers匹配AMQP消息头而不是路由键,其交换器和direct交换器完全一致,但性能差很多,目前基本不用。

3.SpringBoot整合RabbitMQ

(1) 安装RabbitMQ

这里可以使用Docker安装,网上教程一大堆,就不详细介绍了。注意记得安装带有management的版本,这种版本可以利用web网页进行管理。安装完成后run的时候记得映射端口。

(2) Web界面操作RabbitMQ
  1. 进入web界面,地址:RabbitMQ安装的主机地址:端口号,端口号为使用docker安装RabbitMQ映射管理web的端口。默认用户名和密码都是:guest。

在这里插入图片描述

  1. 进入成功后点击Queues添加消息队列,点击Add a new queue,这里的name是路由键路由的依据。

在这里插入图片描述

  1. 点击Exchanges设置交换器,点击Add a new exchanget添加交换器。选择相应的路由类型,并绑定消息队列。这里以direct类型为例演示。
    在这里插入图片描述
  2. 利用设置好的交换器和消息队列进行演示
    点击publish message,进行如下的填写,publish message按钮,就可在对应的消息队列中收到消息。

在这里插入图片描述然后切换到queues中,点击time消息队列,然后点击get Message。就可以获取到刚才发送给消息队列的消息。
在这里插入图片描述

三、SpringBoot整合RabbitMQ

整合过程 比较简单。导入相应的starter就可以,不需要我们做过多的配置,不得不佩服springboot自动配置功能的强大。

1、导入相应的starter

在这里插入图片描述

2、配置RabbitMQ,在application.yml文件中进行RabbitMQ的配置,这里只需指定RabbitMQ软件所在主机地址,其他的使用默认配置就可以。

在这里插入图片描述

3、SpringBoot操作RabbitMQ代码

通过以下代码就可以操作RabbitMQ。

@RunWith(SpringRunner.class)
@SpringBootTest
public class RabbitmqApplicationTests {
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 1. 单播(点对点)
     */
    @Test
    public void contextLoads() {
        // message需要自己构造,定制消息体内容和消息头
        // rabbitTemplate.send(exchange,routeKey,message);
        // Object默认当成消息体,只需要传入要发送的对象,自动序列化发送给rabbitmq
        //rabbitTemplate.convertAndSend(exchange,routeKey,object);
        Map<String,Object> map = new HashMap<>();
        map.put("msg","这是第一个消息");
        map.put("data", Arrays.asList("helloWorld",123,true));
        // 对象使用默认序列化方法以后发送出去
        rabbitTemplate.convertAndSend("exchange.direct","time.news",map);
    }

    @Test
    public void test(){
        Object o = rabbitTemplate.receiveAndConvert("time.news");
        System.out.println(o.getClass());
        System.out.println(o);
    }

    // 定制自己的序列化方法,进行发送。需要配置自己MessageConvert,让对象以json的数据发送出去
    @Test
    public void test1(){
        Map<String,Object> map = new HashMap<>();
        map.put("msg","这是第一个消息");
        map.put("data", Arrays.asList("helloWorld",123,true));
        // 对象使用默认序列化方法以后发送出去
        rabbitTemplate.convertAndSend("exchange.direct","time.news",map);
    }
}

4、监听消息队列

假设有这样一个需求,当消息队列中存放消息时,让程序就可以直接getMassage。SpringBoot为我们提供了@RabbitMQListener注解。

 * @author Time
 * @created 2019/8/27
 *
 *
 * 注解@RabbitListener:监听一或多个个消息队列,当消息队列中存放消息,就获取消息
 */
@Service
public class RabbitMQService {
    @RabbitListener(queues = {"time.news"})
    public void receive(Map<String,Object> map){
        System.out.println(map);
    }
}


在这里插入图片描述

5、AmqpAdmin管理Rabbit组件,之前我们添加交换器、队列都是在web界面进行创建的,除此之外还可以利用AmqpAdmin进行管理这些组件。
  // 利用AmqpAdmin管理组件
    @Autowired
    AmqpAdmin amqpAdmin;
    @Test
    public void test2(){
        // 利用amqpAdmin创建交换器
        amqpAdmin.declareExchange(new DirectExchange("amqp"));
        // 利用amqpAdmin创建消息队列
        amqpAdmin.declareQueue(new Queue("amqp.queue",true));
        // 利用amqpAdmin将交换器和队列绑定
        amqpAdmin.declareBinding(new Binding("amqp.queue", Binding.DestinationType.QUEUE,
                "amqp","amqp",null ));

    }

执行后结果

创建的交换器
在这里插入图片描述创建的消息队列
在这里插入图片描述将交换器和消息队列绑定
在这里插入图片描述

发布了66 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Time__Lc/article/details/100089362