Spring Boot 整合 RabbitMQ

1. 前言

RabbitMQ是一个消息队列,消息队列的功能主要用来

  1. 实现应用服务的异步和解耦,削锋填谷、消息分发;
  2. 解耦;
  3. 在分布式系统中,也可用于其他地方,如分布式事务的支持(阿里的RocketMQ)。

2. RabbitMQ介绍

RabbitMQ是实现AMQP的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。RabbitMQ主要是为了实现系统之间的双向解耦。当生产者大量生产消息时,消费者无法快速消费,就需要一个中间层保存这些数据。

AMQP,即 Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。AMQP 的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。

RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP 等,支持 AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

3. 概念介绍

生产者、消费者和我们的队列。在 RabbitMQ 中,中间还增加了一层:交换机(Exchange)。这样,消息的投递就不由生产者来决定投递至哪个队列,而消息是直接投递至交换机的,由交换机根据调度策略来决定这个消息需要投递到哪个队列。

P:消息的生产者
X:交换机
右侧红色的代表队列

3.1 交换机(Exchange)

问:为什么需要交换机?

答:AMQP协议的核心思想就是生产者和消费者的解耦。生产者讲消息发送到一个交换机,先由交换机来接受,再按照交换机特定的策略转发到Queue进行存储。

问:交换机收到消息,它是如何确定要把哪些消息发送到哪些Queue?

答:Binding和RoutingKey

Binding表示Exchange和Queue之间的关系,表示队列与该交换机绑定,绑定可以附带一个参数RoutingKey。交换机就是根据这个RoutingKey和当前所有绑定的Binding做匹配,如果满足匹配,就往交换机所绑定的Queue发送消息,这样我们向RabbitMQ发送一次消息,就可以分发到不同的Queue。Routing的意义依赖于交换机的类型。

下面依次介绍Exchange的三种主要类型:Direct、Topic、Fanout。

3.1.1 Direct Exchange

Direct Exchange是RabbitMQ默认的Exchange,完全根据RoutingKey来路由消息。例如P发送消息的RoutingKey=binding1,则消息进入Queue1。设置Exchange和Queue的Binding时需指定RoutingKey(一般为Queue的名称),发消息时也指定一样的RoutingKey,消息就会被路由到对应的Queue。

3.1.2 Topic Exchange

Topic Exchange 和 Direct Exchange 类似,也需要通过 RoutingKey 来路由消息,区别在于Direct Exchange 对 RoutingKey 是精确匹配,而 Topic Exchange 支持模糊匹配。分别支持 * 和 # 通配符,* 表示匹配一个单词, # 则表示匹配没有或者多个单词。

3.1.3 Headers Exchange

Headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。 在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。

3.1.4 Default Exchange

Default Exchange 是一种特殊的 Direct Exchange。当你手动创建一个队列时,后台会自动将这个队列绑定到一个名称为空的 Direct Exchange 上,绑定 RoutingKey 与队列名称相同。有了这个默认的交换机和绑定,使我们只关心队列这一层即可,这个比较适合做一些简单的应用。

3.1.5 RPC

MQ本身是基于异步的消息处理,前面的示例中所有的生产者(P)将消息发送到RabbitMQ后不会知道消费者(C)处理成功或者失败(甚至连有没有消费者来处理这条消息都不知道)。 但实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后再进行下一步处理。这相当于RPC(Remote Procedure Call,远程过程调用)。在RabbitMQ中也支持RPC。

RabbitMQ中实现RPC的机制是:

  • 客户端发送请求(消息)时,在消息的属性(MessageProperties ,在AMQP 协议中定义了14中properties ,这些属性会随着消息一起发送)中设置两个值replyTo (一个Queue 名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue 中)和correlationId (此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败)
  • 服务器端收到消息并处理
  • 服务器端处理完消息后,将生成一条应答消息到replyTo 指定的Queue ,同时带上correlationId 属性
  • 客户端之前已订阅replyTo 指定的Queue ,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理。

4. Spring Boot 整合 RabbitMQ

Spring Boot 整合 RabbitMQ 非常简单,如果只是简单的使用配置非常少,Spring Boot 提供了 spring-boot-starter-amqp 项目对消息各种支持。

  1. 引入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

     

  2. 配置RabbitMQ
    # rabbitmq配置
    spring.rabbitmq.host=localhost
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=123456
    spring.rabbitmq.virtual-host=scheduled_vhost
    spring.rabbitmq.publisher-confirms=true
    spring.rabbitmq.publisher-returns=true
    spring.rabbitmq.listener.direct.acknowledge-mode=manual
    spring.rabbitmq.listener.simple.acknowledge-mode=manual
    spring.rabbitmq.listener.simple.concurrency=10
    spring.rabbitmq.listener.simple.max-concurrency=50
    #队列名称
    spring.rabbitmq.template.queue=ctv_els_refresh_data

     

  3. 简单使用
@Slf4j
@Component
public class MqConfiguration {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void sendMessage(String name, String creditCode, String regNo) {
        Map map = new HashMap<>();
        map.put("name", name);
        map.put("credit_no", creditCode);
        map.put("reg_no", regNo);
        rabbitTemplate.convertAndSend("ctv_els_refresh","", map);
        log.info(">>> 队列发送成功:{}-{}",creditCode , name);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值