RabbitMQ整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。
Producer:生产者创建消息,然后发布到RabbitMQ中,消息一般可以包含2个部分:消息体payload和标签Label。
Consumer:消费者连接到RabbitMQ服务器,并订阅到队列上。当消费者消费一条消息时,只是消费消息的消息体。在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只有消息体。
Broker:对于RabbitMQ来说,一个RabbitMQ Broker可以简单地看作一个RabbitMQ服务节点,或者RabbitMQ服务实例。
Queue:队列,是RabbitMQ的内部对象,用于存储消息。RabbitMQ中消息都只能存储在队列中。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(轮询)给多个消费者进行处理。RabbitMQ不支持队列层面的广播消费。
Exchange:交换器。生产者将消息发送到Exchange,由交换器将消息路由到一个或者多个队列中。如果路由不到,或许会返回给生产者,或许直接丢弃。
RoutingKey:路由键。生产者发送消息给交换器的时候,一般会指定一个RoutingKey,用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键BindingKey联合使用才能最终生效。生产者通过指定RoutingKey来决定消息流向哪里。
Binding:绑定。通过绑定将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键BindingKey。BindingKey并不是在所有的情况下都生效,它依赖于交换器类型。如fanout类型的交换器就会无视BindingKey,而是将消息路由到所有绑定该交换器的队列中。
BindingKey:其实也属于路由键的一种。
注意:BindingKey是将交换器和队列绑定时指定的规则,而RoutingKey是发送消息时给消息设置的路由。
在direct交换器类型下,RoutingKey和BindingKey需要完全匹配才能使用。但是在topic交换器类型下,RoutingKey和BindingKey之间需要做模糊匹配。
RabbitMQ常用的交换器类型有fanout、direct、topic、headers这四种。AMQP协议里还提到另外两种类型:System和自定义。
topic交换器的匹配规则:RoutingKey和BindingKey为一个点号分隔的字符串。BindingKey中可以存在两种特殊的字符串*和#。*用于匹配一个单词,#用于匹配多个规格单词(可以是零个)。
headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。headers类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。
和RabbitMQ Broker建立的连接是一个TCP连接,也就是Connection。建立连接后,客户端就可以创建一个AMQP信道,每个信道(Channel)都会被指派一个唯一的ID,信道是建立在Connection之上的虚拟连接,RabbitMQ处理的每条AMQP指令都是通过信道完成的。RabbitMQ采用类似NIO的做法(非阻塞IO三大核心部分:Channel信道、Buffer缓冲区、Selector选择器,数据总是从信道读取到缓存区中,或者从缓存区写入到信道中,Selector用于监听多个信道的事件。因此单线程可以监听多个数据的信道,典型的有Reactor模式),选择了TCP连接复用,不仅可以减少性能开销,同时也便于管理。
每个线程把持一个信道,所以信道复用了Connection的TCP连接。同时RabbitMQ可以确保每个线程的私密性。所以当每个信道的流量不是很大是,复用但一个连接可以在产生性能瓶颈的情况下有效地节省TCP连接资源。
AMQP协议包括三层:模块层(最高层,主要定义了一些供客户端调用的命令)、会话层(主要负责将客户端的命令发送给服务器,为通信提供可靠性同步机制和错误处理)、运输层(主要传输二进制数据流,提供帧的处理、信道复用、错误检测和数据表示等)。
AMQP本身是应用层的协议,其填充于TCP协议层的数据部分。AMQP协议可以看作一系列结构化的命令的集合,这里的命令代表一种操作。类似于HTTP中的方法。
AMQP生产者流转过程:
Basic.publish命令还包含了Content Header(消息体的属性)和Content Body(消息本身)。
AMQP消费者流传过程:
AMQP命令概览: