RabbitMQ消息队列详解(图文并茂)
RabbitMQ 是使用 Erlang 编写的一个开源的消息队列,本身支持很多的协议,包括 AMQP、XMPP、SMTP 和 STOMP。正是如此,它的重量级很大,更适合于企业级的开发。
同时,RabbitMQ 实现了一个经纪人(Broker)构架,意味着消息在发送给客户端时先在中心队列排队,对路由(Routing)、负载均衡(Load balance)或者数据持久化都有很好的支持,是高可用的主从架构。另外,它还支持常用的多种语言客户端,比如 C++、Java、.Net、Python、PHP、Ruby 等。
消息队列通常会涉及三个概念:生产者(发消息者)、消息队列、消费者(收消息者)。RabbitMQ 在这三个基本概念之上又加入了路由的概念,即在生产者和消息队列之间增加了一个交换器(Exchange),生产者把消息发给交换器,交换器再根据调度策略把消息转发给消息队列。因此,生产者和消息队列之间没有直接的关系,消息队列起到储存消息的作用,等待消费者取出消息。
RabbitMQ 的具体执行过程如下图所示:
RabbitMQ 运作过程中涉及如下几个概念:
交换器的调度策略与三个因素有关:Exchange Type(交换器类型)、Biding Key(绑定键)、Routing Key(路由键)。
交换器调度过程:交换器与队列进行绑定,并设定一个绑定键。生产者发消息给交换器时,还需要指定交换器和路由键来设定这个消息的发送规则,即最终这个消息会流向哪个队列,消费者只需要配置队列表示从哪个队列获取消息即可。Exchange Type、Biding Key 和 Routing Key 要联合使用才可以生效。
RabbitMQ 中也有一种策略是与 Biding Key 和 Routing Key 无关的,即只需要交换器和队列绑定就会将消息发送到所有绑定该交换器的队列上,类似于广播。下面就来看看交换器是哪种调度模式。
RabbitMQ 主要有 Fanout、Direct、Topic、Headers 和 Dead Letter 五种交换器模式,这里主要讲解前三种常用的交换器模式。
1) Fanout(订阅模式/广播模式),如下图所示。
扇形交换器会把所有接收到的消息都分发到与之绑定的队列中。此种模式是没有 Biding Key 和 Routing Key 概念的,即与 Biding Key 和 Routing Key 无关,类似于子网广播,子网内的每台主机都能获得一份复制的消息。相较于其他策略,Fanout Exchange 转发消息的效率最高,工作模式如下图所示。
2) Direct(点对点模式),如下图所示。
直连型交换器是一种精确匹配模式,即需要生产者发送消息时绑定的 Routing Key,需要和绑定 Exchange、Queue 的 Biding Key 完全匹配,才能将消息分发到对应的队列上。
另外,RabbitMQ 默认提供了一个 Exchange,交换器名字是空字符串,交换器类型是 Direct,绑定到所有的Queue,每一个 Queue 和这个无名 Exchange 之间的 Binding Key 是 Queue 的名字,所以有时我们感觉不需要交换器也可以发送和接收消息,实际上是使用了 RabbitMQ 默认提供的 Exchange,工作模式如下图所示。
3) Topic(通配符模式),如下图所示:
主题交换器是一种模糊匹配模式,是生产者发消息 Routing Key 与交换器、队列之间绑定的 Binding Key 进行模糊匹配,如果匹配成功,就将消息分发到对应的 Queue。工作模式如下图所示:
Routing Key 和 Binding Key 是一段字符串,用“.”进行分隔,分隔开的每段独立字符串称为一个单词。通配符构成的 key 一般是用来和队列进行绑定的,即用于 Binding Key 的设定。通配键可以用“#”和“*”两种特殊字符作为通配符,其中“#”可以匹配任意数量(零个或多个),“*”可以匹配一个单词,是必须出现的。下面通过例子讲解一下这两种通配符。
场景:
测试:
同时,RabbitMQ 实现了一个经纪人(Broker)构架,意味着消息在发送给客户端时先在中心队列排队,对路由(Routing)、负载均衡(Load balance)或者数据持久化都有很好的支持,是高可用的主从架构。另外,它还支持常用的多种语言客户端,比如 C++、Java、.Net、Python、PHP、Ruby 等。
消息队列通常会涉及三个概念:生产者(发消息者)、消息队列、消费者(收消息者)。RabbitMQ 在这三个基本概念之上又加入了路由的概念,即在生产者和消息队列之间增加了一个交换器(Exchange),生产者把消息发给交换器,交换器再根据调度策略把消息转发给消息队列。因此,生产者和消息队列之间没有直接的关系,消息队列起到储存消息的作用,等待消费者取出消息。
RabbitMQ 的具体执行过程如下图所示:

RabbitMQ 运作过程中涉及如下几个概念:
术语 | 说明 |
---|---|
Channel(信道) | 多路复用连接中的一条独立的双向数据流通道,建立在真实 TCP 连接内的虚拟连接。 |
Producer(生产者) | 向消息队列发布消息的客户端应用程序。 |
Consumer(消费者) | 从消息队列取得消息的客户端应用程序。 |
Message(消息) | 由消息头和消息体组成;消息体不透明,消息头包含路由键、优先级、持久性等属性。 |
Routing Key(路由键) | 消息头属性,用于标记路由规则,决定交换器转发路径,最大长度 255 字节。 |
Queue(消息队列) | 存储消息的数据结构,保存消息直到被消费者取走;多个消费者订阅同一队列时消息平均分摊。 |
Exchange(交换器/路由器) | 接收生产者消息并按路由规则转发到队列;不存储消息,无绑定队列时丢弃消息。 |
Binding(绑定) | 建立 Exchange 与 Queue 的关联,通过 Binding Key 定义路由规则,构成路由表。 |
Binding Key(绑定键) | Exchange 与 Queue 的绑定关系,用于匹配 Routing Key,最大长度 255 字节。 |
Broker | RabbitMQ Server,即服务器实体。 |
Exchange(交换器)调度模式
交换器消息调度模式指的是交换器在收到生产者发送的消息后,依据某种规则把消息转发到一个或多个队列中保存。交换器的调度策略与三个因素有关:Exchange Type(交换器类型)、Biding Key(绑定键)、Routing Key(路由键)。
交换器调度过程:交换器与队列进行绑定,并设定一个绑定键。生产者发消息给交换器时,还需要指定交换器和路由键来设定这个消息的发送规则,即最终这个消息会流向哪个队列,消费者只需要配置队列表示从哪个队列获取消息即可。Exchange Type、Biding Key 和 Routing Key 要联合使用才可以生效。
RabbitMQ 中也有一种策略是与 Biding Key 和 Routing Key 无关的,即只需要交换器和队列绑定就会将消息发送到所有绑定该交换器的队列上,类似于广播。下面就来看看交换器是哪种调度模式。
RabbitMQ 主要有 Fanout、Direct、Topic、Headers 和 Dead Letter 五种交换器模式,这里主要讲解前三种常用的交换器模式。
1) Fanout(订阅模式/广播模式),如下图所示。

扇形交换器会把所有接收到的消息都分发到与之绑定的队列中。此种模式是没有 Biding Key 和 Routing Key 概念的,即与 Biding Key 和 Routing Key 无关,类似于子网广播,子网内的每台主机都能获得一份复制的消息。相较于其他策略,Fanout Exchange 转发消息的效率最高,工作模式如下图所示。

2) Direct(点对点模式),如下图所示。

直连型交换器是一种精确匹配模式,即需要生产者发送消息时绑定的 Routing Key,需要和绑定 Exchange、Queue 的 Biding Key 完全匹配,才能将消息分发到对应的队列上。
另外,RabbitMQ 默认提供了一个 Exchange,交换器名字是空字符串,交换器类型是 Direct,绑定到所有的Queue,每一个 Queue 和这个无名 Exchange 之间的 Binding Key 是 Queue 的名字,所以有时我们感觉不需要交换器也可以发送和接收消息,实际上是使用了 RabbitMQ 默认提供的 Exchange,工作模式如下图所示。

3) Topic(通配符模式),如下图所示:

主题交换器是一种模糊匹配模式,是生产者发消息 Routing Key 与交换器、队列之间绑定的 Binding Key 进行模糊匹配,如果匹配成功,就将消息分发到对应的 Queue。工作模式如下图所示:

Routing Key 和 Binding Key 是一段字符串,用“.”进行分隔,分隔开的每段独立字符串称为一个单词。通配符构成的 key 一般是用来和队列进行绑定的,即用于 Binding Key 的设定。通配键可以用“#”和“*”两种特殊字符作为通配符,其中“#”可以匹配任意数量(零个或多个),“*”可以匹配一个单词,是必须出现的。下面通过例子讲解一下这两种通配符。
场景:
- 一个主题交换器:TopicExchange。
- 三个队列:Queue1、Queue2、Queue3。
- TopicExchange 和 Queue1 的绑定键为 TT.*,和 Queue2 的绑定键为 TT.#,和 Queue3 的绑定键为 *.TT.*。
测试:
- 如果消息 Message1 携带的路由键 Routing Key 为 TT.A,那么这条消息将会被 Queue1 和 Queue2 收到。
- 如果消息 Message2 携带的路由键 Routing Key 为 TT,那么这条消息将只会被 Queue2 收到。
- 如果消息 Message3 携带的路由键 Routing Key 为 TT.AA.BB,那么这条消息将只会被 Queue2 收到。
- 如果消息 Message4 携带的路由键 Routing Key 为 A.TT.B,那么这条消息将只会被 Queue3 收到。