RabbitMQ-CheatSheet
RabbitMQ CheatSheet
一、消息队列
消息队列中间件
- 项目解耦:不同的项目或模块可以使用消息中间件进行数据的传递,从而可以保证模块的相对独立,实现解耦。
- 流量削峰:可以将突发的流量
( 如秒杀数据) 写入消息中间件,然后由多个消费者进行异步处理。 - 弹性伸缩:可以通过对消息中间件进行横向扩展来提高系统的处理能力和吞吐量。
- 发布订阅:可以用于任意的发布订阅模式中。
- 异步处理:当我们不需要对数据进行立即处理,或者不关心数据的处理结果时,可以使用中间件进行异步处理。
- 冗余存储:消息中间件可以对数据进行持久化存储,直到你消费完成后再进行删除。
二、AMQP 协议
- Module Layer:位于协议最高层,主要定义了一些供客户端调用的命令,客户端可以利用这些命令实现自己的业务逻辑。例如:可以使用
Queue.Declare 命令声明一个队列或者使用Basic.Consume 订阅消费一个队列中的消息。 - Session Layer:位于中间层,主要负责将客户端的命令发送给服务器,再将服务端的应答返回给客户端,主要为客户端与服务器之间的通信提供可靠性同步机制和错误处理。
- Transport Layer:位于最底层,主要传输二进制数据流 ,提供帧的处理、信道复用、错误检测和数据表示等。
三、RabbitMQ 简介
AMQP 0-9-1
的基础上还进行了额外拓展,并可以通过插件来支持 AMQP 1.0
。所以在某种程度上而言,
- 支持多种消息传递协议,除了
AMQP 外,还可以通过插件支持所有版本的STOMP 协议和MQTT 3.1 协议; - 拥有丰富的交换器类型,可以满足绝大部分的使用需求;
- 支持多种部署方式,易于部署;
- 支持跨语言开发,如:Java,.NET,PHP,Python,JavaScript,Ruby,Go;
- 可以通过集群来实现高可用性和高吞吐,还可以通过
Federation 插件来连接跨机房跨区域的不同版本的服务节点; - 插拔式的身份验证和授权,支持
TLS 和LDAP ; - 支持持续集成,能够使用各种插件进行灵活地扩展;
- 能够使用多种方式进行监控和管理,如
HTTP API ,命令行工具和UI 界面。
四、模型架构

1. Publisher(发布者)
发布者
2. Message(消息)
消息由消息头和消息体组成。消息头用于存储与消息相关的元数据:如目标交换器的名字
3. Exchange(交换器)
交换器负责接收来自生产者的消息,并将将消息路由到一个或者多个队列中,如果路由不到,则返回给生产者或者直接丢弃,这取决于交换器的
- 当
mandatory 为true 时:如果交换器无法根据自身类型和路由键找到一个符合条件的队列,则会将该消息返回给生产者; - 当
mandatory 为false 时:如果交换器无法根据自身类型和路由键找到一个符合条件的队列,则会直接丢弃该消息。
4. BindingKey ( 绑定键)
交换器与队列通过
5. Routingkey(路由键)
生产者将消息发给交换器的时候,一般会指定一个
6. Queue(消息队列)
用于存储路由过来的消息。多个消费者可以订阅同一个消息队列,此时队列会将收到的消息将以轮询
7. Consumer(消费者)
消费者订阅感兴趣的队列,并负责消费存储在队列中的消息。为了保证消息能够从队列可靠地到达消费者,
- 当
autoAck 为true 时:此时消息发送出去( 写入TCP 套接字) 后就认为消费成功,而不管消费者是否真正消费到这些消息。当TCP 连接或channel 因意外而关闭,或者消费者在消费过程之中意外宕机时,对应的消息就丢失。因此这种模式可以提高吞吐量,但会存在数据丢失的风险。 - 当
autoAck 为false 时:需要用户在数据处理完成后进行手动确认,只有用户手动确认完成后,RabbitMQ 才认为这条消息已经被成功处理。这可以保证数据的可靠性投递,但会降低系统的吞吐量。
8. Connection(连接)
用于传递消息的
9. Channel(信道)
10. Virtual Host(虚拟主机)
/
。
11. Broker
一个真实部署运行的
五、交换器类型
5.1 fanout
这是最简单的一种交换器模型,此时会把消息路由到与该交换器绑定的所有队列中。如下图,任何发送到

5.2 direct
把消息路由到

需要特别说明的是一个交换器绑定多个队列时,它们的

5.3 topic
将消息路由到
RountingKey 和BindingKey 由多个单词使用逗号.
进行连接;BindingKey 支持两个特殊符号:#
和*
。其中*
用于匹配一个单词,#
用于匹配零个或者多个单词。
以下是官方文档中的示例,交换器与队列的绑定情况如图所示,此时的路由情况如下:

- 路由键为
lazy.orange.elephant
的消息会发送给所有队列; - 路由键为
quick.orange.fox
的消息只会发送给Q1 队列; - 路由键为
lazy.brown.fox
的消息只会发送给Q2 队列; - 路由键为
lazy.pink.rabbit
的消息只会发送给Q2 队列; - 路由键为
quick.brown.fox
的消息与任何绑定都不匹配; - 路由键为
orange
或quick.orange.male.rabbit
的消息也与任何绑定都不匹配。
5.4 headers
在交换器与队列进行绑定时可以指定一组键值对作为x-match
参数指定匹配模式:
- x-match = all :所有的键值对都相同才算匹配成功;
- x-match = any:只要有一个键值对相同就算匹配成功。
六、死信队列
- 消息被拒绝
(Basic.Reject/Basic.Nack) ,井且设置重回队列的参数requeue 为false ; - 消息过期;
- 队列达到最大长度。
我们可以在队列创建的
// 创建死信交换器
channel.exchangeDeclare("exchange.dlx", "direct");
// 声明死信队列
channel.queueDeclare(" queue.d1x ", true, false, false, null);
// 绑定死信交换器和死信队列
channel.queueBind("queue.dlx ", "exchange.dlx ", "routingkey");
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", "exchange.dlx");
// 为名为 myqueue 的正常队列指定死信交换器
channel.queueDeclare("queue.normal", false, false, false, args);
除此之外,您还可以重新指定死信的路由键,如果没有指定,则默认使用原有的路由键,重新设置的方法如下:
args.put("x-dead-letter-routing-key", "some-routing-key");
参考资料
- 朱忠华
. RabbitMQ 实战指南. 电子工业出版社. 2017-11-1 - 官方文档:RabbitMQ Tutorials 、Documentation: Table of Contents