RabbitMQ是什么,RabbitMQ快速入门(新手必看)
RabbitMQ 作为流行的消息中间件,实现了应用程序的异步和解耦,同时也能起到消息缓冲、消息分发的作用。
消息中间件在互联网公司使用的越来越多,主要用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息队列实现系统之间的双向解耦,生产者往消息队列中发送消息,消费者从队列中拿取消息并处理,生产者不用关心是谁来消费,消费者不用关心谁在生产消息,从而达到系统解耦的目的,也大大提高了系统的高可用性和高并发能力。
RabbitMQ 基于开源的 AMQP 协议实现,服务器端用 Erlang 语言编写,支持多种客户端,如 Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP、AJAX等。
RabbitMQ 的主要优势如下:
基于 AMQ 协议的客户端可与消息中间件传递消息,从而不受产品、开发语言等条件限制。消息中间件主要用于组件之间的解耦,消息发送者无须知道消息使用者的存在,反之亦然。
与其他消息队列协议不同的是,AMQP 中增加了 Exchange 和 Binging 角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收;而 Binding 决定 Exchange 的消息应该发送到哪个队列。
下图展示的就是消息路由传递的过程:

图 1 AMQP 消息路由的过程
生产者首先将消息发送到 Exchange,通过 Exchange 转发到绑定的各个消息队列上,然后消费者从队列中读取消息。

图 2 RabbitMQ 的功能组件
通常我们谈到消息队列服务时有 3 个基本概念:消息发送者、消息队列和消息接收者。RabbitMQ在这些基本概念之上多做了一层抽象,在消息发送者和消息队列之间加入了交换机,这样消息发送者与队列之间就没有直接联系,变成消息发送者将消息发送给交换机,再由交换机根据调度策略把消息发送到各个队列。
但是我们给交换机发送消息,它怎么知道给哪个消息队列发送呢?这里就要用到 RoutingKey 和 BindingKey:
当消息发送到交换机(Exchange)时,通过消息携带的 RoutingKey 与当前交换机所有绑定的 BindingKey 进行匹配,如果满足匹配规则,则往 BindingKey 所绑定的消息队列发送消息,这样就解决了向 RabbitMQ 发送一次消息,可以分发到不同的消息队列,实现消息路由分发的功能。
交换机有 Direct、Topic、Headers 和 Fanout 四种消息分发类型。不同的类型在处理绑定到队列方面的行为时会有所不同:

图 3 Direct消息转发模式
当消息的 RoutingKey 为 orange 时,匹配 Q1 队列,所以消息被发送到 Q1。

图 4 Topic 消息转发模式
Topic 与 Direct 类似,只是路由匹配上支持通配符,可以使用以下两个通配符:
当消息的 RoutingKey 为 color.orange.msg 时,匹配 Q1 队列,所以消息被发送到 Q1。
消息队列绑定的 header 数据中有一个特殊的键 x-match,有 all 和 any 两个值:

图 5 Header消息转发模式
如上图所示,在绑定队列与交换机时指定一组“键-值对”,当消息发送到交换机时,RabbitMQ 会取到该消息的 Headers,然后对比其中的“键-值对”是否匹配队列与 Exchange 绑定时指定的“键-值对”;如果匹配则消息会路由到该队列,否则不会路由到该队列。

图 6 Fanout 消息转发模式
如上图所示,每个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout 模式转发消息是最快的。
消息中间件在互联网公司使用的越来越多,主要用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。消息队列实现系统之间的双向解耦,生产者往消息队列中发送消息,消费者从队列中拿取消息并处理,生产者不用关心是谁来消费,消费者不用关心谁在生产消息,从而达到系统解耦的目的,也大大提高了系统的高可用性和高并发能力。
RabbitMQ 基于开源的 AMQP 协议实现,服务器端用 Erlang 语言编写,支持多种客户端,如 Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP、AJAX等。
RabbitMQ 的主要优势如下:
优势 | 描述 |
---|---|
可靠性(Reliability) | 使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认。 |
灵活的路由(Flexible Routing) | 在消息进入队列之前,通过 Exchange 来路由消息。对于典型的路由功能,Rabbit 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,既可以将多个 Exchange 绑定在一起,又可以通过插件机制实现自己的 Exchange。 |
消息集群(Clustering) | 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker。 |
高可用(Highly Available Queues) | 队列可以在集群中的机器上进行镜像,使得在部分节点出现问题的情况下队列仍然可用。 |
多种协议(Multi-Protocol) | 支持多种消息队列协议,如 STOMP、MQTT 等。 |
多种语言客户端(Many Clients) | 几乎支持所有常用语言,比如 Java、.NET、Ruby 等。 |
管理界面(Management UI) | 提供了易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。 |
跟踪机制(Tracing) | 如果消息异常,RabbitMQ 提供了消息的跟踪机制,使用者可以找出发生了什么。 |
插件机制(Plugin System) | 提供了许多插件进行扩展,也可以编辑自己的插件。 |
AMQP
AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是应用层协议的开放标准,是为面向消息的中间件设计。基于 AMQ 协议的客户端可与消息中间件传递消息,从而不受产品、开发语言等条件限制。消息中间件主要用于组件之间的解耦,消息发送者无须知道消息使用者的存在,反之亦然。
与其他消息队列协议不同的是,AMQP 中增加了 Exchange 和 Binging 角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收;而 Binding 决定 Exchange 的消息应该发送到哪个队列。
下图展示的就是消息路由传递的过程:

图 1 AMQP 消息路由的过程
生产者首先将消息发送到 Exchange,通过 Exchange 转发到绑定的各个消息队列上,然后消费者从队列中读取消息。
RabbitMQ组件功能
RabbitMQ 中有几个非常重要的组件:服务实体(Broker)、虚拟主机(Virtual Host)、交换机(Exchange)、队列(Queue)和绑定(Binging)等,如下图所示。
图 2 RabbitMQ 的功能组件
- 服务实体(Broker):标识消息队列的服务器实体。
- 虚拟主机(Virtual Host):一个虚拟主机只有一组交换机、队列和绑定,为什么还需要多个虚拟主机呢?很简单,在 RabbitMQ 中,用户只能在虚拟主机的粒度上进行权限控制。因此,如果需要禁用 A 组访问 B 组的交换机/队列/绑定,就必须为 A 和 B 分别创建一个虚拟主机,每个 RabbitMQ 服务器都有一个默认的虚拟主机“/”。
- 交换机(Exchange):客户端不会直接给服务端发送消息,而是通过交换机转发。交换机用于转发消息,但是它不会进行存储,如果没有消息队列发送到交换机,它就会直接丢弃生成者(Producer)发送过来的消息。
- 队列(Queue):用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列中,等待消费者连接到这个队列将其取走。
- 绑定(Binging):也就是交换机需要与队列相互绑定,如图 2 所示就是多对多的关系。
通常我们谈到消息队列服务时有 3 个基本概念:消息发送者、消息队列和消息接收者。RabbitMQ在这些基本概念之上多做了一层抽象,在消息发送者和消息队列之间加入了交换机,这样消息发送者与队列之间就没有直接联系,变成消息发送者将消息发送给交换机,再由交换机根据调度策略把消息发送到各个队列。
交换机
交换机(Exchange)的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,只是把消息分发给各自的队列。但是我们给交换机发送消息,它怎么知道给哪个消息队列发送呢?这里就要用到 RoutingKey 和 BindingKey:
- BindingKey 是交换机和消息队列绑定的规则描述;
- RoutingKey 是消息发送时携带的消息路由信息描述。
当消息发送到交换机(Exchange)时,通过消息携带的 RoutingKey 与当前交换机所有绑定的 BindingKey 进行匹配,如果满足匹配规则,则往 BindingKey 所绑定的消息队列发送消息,这样就解决了向 RabbitMQ 发送一次消息,可以分发到不同的消息队列,实现消息路由分发的功能。
交换机有 Direct、Topic、Headers 和 Fanout 四种消息分发类型。不同的类型在处理绑定到队列方面的行为时会有所不同:
- Direct:其类型的行为是“先匹配,再发送”,即在绑定时设置一个 BindingKey,当消息的 RoutingKey 匹配队列绑定的 BindingKey 时,才会被交换机发送到绑定的队列中。
- Topic:按规则转发消息(最灵活)。支持用“*”或“#”的模式进行绑定。“*”表示匹配一个单词,“#”表示匹配 0 个或者多个单词。比如,某消息队列绑定的 BindingKey 为“*.user.#”时,能够匹配到 RoutingKey 为 usd.user 和 eur.user.db 的消息,但是不匹配user.hello。
- Headers:设置 header attribute 参数类型的交换机。根据应用程序消息的特定属性进行匹配,这些消息可能在绑定 key 中标记为可选或者必选。
- Fanout:转发消息到所有绑定队列(广播)。将消息广播到所有绑定到它的队列中,而不考虑队列绑定的 BindingKey 的值。
1) Direct模式
Direct 是 RabbitMQ 默认的交换机模式,也是简单的模式,根据 key 全字匹配去寻找队列,如下图所示:
图 3 Direct消息转发模式
当消息的 RoutingKey 为 orange 时,匹配 Q1 队列,所以消息被发送到 Q1。
2) Topic模式
Topic 是 RabbitMQ 中使用最多的交换机模式(见下图),RoutingKey 必须是一串字符,用符号“.”隔开,比如 user.msg 或者 user.order.msg 等。
图 4 Topic 消息转发模式
Topic 与 Direct 类似,只是路由匹配上支持通配符,可以使用以下两个通配符:
- *:表示匹配一个词;
- #:表示匹配 0 个或多个词。
当消息的 RoutingKey 为 color.orange.msg 时,匹配 Q1 队列,所以消息被发送到 Q1。
3) Headers模式
Headers 也是根据规则匹配的,相较于 Direct 和 Topic 固定地使用 RoutingKey 与 BindingKey 的匹配规则来路由消息,Headers 是根据发送的消息内容中的 headers 属性进行匹配的。消息队列绑定的 header 数据中有一个特殊的键 x-match,有 all 和 any 两个值:
- all:表示传送消息的 header 中的“键-值对”(Key-Value Pair)和交换机的 header 中的“键-值对”全部匹配,才可以路由到对应的交换机。
- any:表示传送消息的 header 中的“键-值对”和交换机的 header 中的“键-值对”中的任意一个匹配,就可以路由到对应的交换机。

图 5 Header消息转发模式
如上图所示,在绑定队列与交换机时指定一组“键-值对”,当消息发送到交换机时,RabbitMQ 会取到该消息的 Headers,然后对比其中的“键-值对”是否匹配队列与 Exchange 绑定时指定的“键-值对”;如果匹配则消息会路由到该队列,否则不会路由到该队列。
4) Fanout模式
Fanout 是消息广播模式,交换机不处理 RoutingKey,发送到交换机的消息都会分发到所有绑定的队列上。Fanout 模式不需要 RoutingKey,只需要提前将交换机与队列进行绑定即可。
图 6 Fanout 消息转发模式
如上图所示,每个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout 模式转发消息是最快的。