在正式介绍 RabbitMQ 基本概念之前,我们先看看 MQ 的消息模型。所有 MQ 产品抽象模型都如下图:
图1:消息流
上图中,拥有三个角色,分别如下:
生产者(Producer):创建消息,然后将创建的消息放入到队列中;
队列(Queue):一个用来存放生产者创建的消息的容器;
消费者(Consumer):订阅一个/多个队列,从队列中获取消息且消费消息;
MQ流程:消费者(consumer)订阅某个队列。生产者(producer)创建消息,然后发布到队列(queue)中,最后将消息发送到监听的消费者。
上面对 MQ 做了最简单抽象的描述,如果具体到 RabbitMQ 则有更详细的概念需要解释。前面章节介绍过 RabbitMQ 是 AMQP 协议的一个开源实现,所以在 AMQP 中存在的基本概念,在 RabbitMQ 中依然存在。下面将逐一介绍:
图2:RabbitMQ 内部结构
消息是指在应用程序之间传递的数据。消息由消息头和消息体组成。消息体(也可以称为 payload)是不透明的,在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如:JSON字符串。而消息头则由一系列的可选属性组成,这些属性包括 routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
生产者,就是投递消息的一方。生产者创建消息,然后将消息发布到 RabbitMQ。在 RabbitMQ 中,实际上生产者是将消息直接发送到交换器,由交换器将消息路由到符合要求的队列中去。
消费者,就是接收消息的一方。消费者连接到 RabbitMQ 服务器,并订阅到指定的队列上。当消费者消费一条消息时,只是消费消息的消息体(payload)。
Broker 表示消息中间件服务节点。对于 RabbitMQ来说,一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ服务节点,或者 RabbitMQ 服务实例。大多数情况下也可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。
队列,是 RabbitMQ 的内部对象,用于存储消息。RabbitMQ 中消息只能存储在队列中,生产者生产的消息最终将投递到队列中,消费者可以从队列中获取消息并进行消费。
多个消费者可以订阅同一个队列,这是队列中的消息将会被平均分摊给多个消费者进行消费,而不是每一个消费者都收到所有的消息并消费。
在 RabbitMQ 中,生产者永远不会直接将消息投递到队列中,而是直接投递给交换器。由交换器将消息路由到一个或多个队列中。如果路由不到,或许会返回给生产者,或许直接丢弃。
交换器的具体示意图如下图:
RabbitMQ 中通过将交换器与队列关联起来,且在绑定的时候一般会指定一个绑定键(BindingKey),这样 RabbitMQ 就知道如何正确地将消息路由到队列了,如下图:
上图中,生产者将消息发送给交换器时,需要一个路由键(RoutingKey),当绑定键和路由键向匹配时,消息会被路由到对应的队列中。在绑定多个队列到同一个交换器的时候,这些绑定允许使用相同绑定键。绑定键并不是在所有的情况下都有效,它依赖于交换器类型,例如 fanout 类型的交换器就会忽略绑定键,而是将消息路由到所有绑定到该交换器的队列中。
生产者将消息发送给交换器时,一般会指定一个路由键,用来指定消息的路由规则,而这个路由键需要与交换器类型和绑定键联合使用才能最终生效。
如果交换器通过绑定键和队列建立了绑定关系,生产者可以在发送消息给交换器时,通过指定路由键来控制消息的流向。
可以将 Connection 认为是一个网络连接,比如一个 TCP 链接。我们可以使用 Connection 来创建多个 Channel 信道实例。但是,Channel 实例不能在线程间共享,应用程序应该为每一个线程创建一个 Channel。某些情况下 Channel 的操作可以并发运行,但是在其他情况下会导致在网络上出现错误的通信帧交错,同时也会影响发送方确认机制的运行。所以,多线程间共享 Channel 实例是非线程安全的。
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。