上一节我们对消息中间件和RabbitMQ本身有了大致印象,本节主要介绍RabbitMQ的模型架构。
相关概念介绍
- 生产者和消费者
Producer: 生产者,投递消息的一方,消息一般包括两个部分:消息体(payload)和标签(label).标签用来描述消息,比如交换器的名称和路由键
Consumer: 消费者,接手消息的一方.
Broker: 消息中间件的服务节点 - 队列
Queue: 队列
RabbitMQ的消息都存储在队列中,多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊,既轮询.RabbitMQ不支持广播消费,也不建议这么做 - 交换器、路由键、绑定
Exchange: 交换器
生产者将消息发送到Exchange,由交换器将消息路由到一个或多个队列中.如果路由不到,就丢弃或返还给生产者.
Routingkey: 路由键
生产者将消息发送给交换器时,会指定一个路由键RoutingKey,用来指定这个消息的路由规则,而这个RoutingKey需要与交换器类型和绑定键(BindingKey)同时使用才会生效.
Binding: 绑定
通过绑定将队列和交换器关联起来,绑定时一般指定一个绑定键(BindingKey),这样在生产者发送消息时就能找到队列了. - 交换器类型
RabbitMQ常用的交换器类型有fanout、direct、topic、headers四种。AMQP协议中还提到另外两种类型:System和自定义
- fanout: 把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中.这是一种类似广播的发送方式.上面说RabbitMQ不支持广播的消息消费,是指从队列到消费者不支持广播.不要混淆.
- direct: 按指定的RoutingKey规则将消息发送到对应BindingKey的队列中,这里的RoutingKey需要完全匹配
- topic: 有相对复杂的匹配规则,如下:
- RoutingKey为一个由
.
分隔的字符串,被.
分隔的每一段字符串称为一个单词,如"com.pctf.routing1"
- BindingKey 和 RoutingKey一样是由
.
分隔的字符串 - BindingKey中可以存在两种特殊字符串
*
和#
,用于模糊匹配.其中*
用于匹配一个单词,#
用于匹配0+个单词
以下图为例;
- headers: 不依赖路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配
RabbitMQ中Connection与Channel的关系
无论是生产者还是消费者,都需要与RabbitMQ的Broker进行连接,每个连接都是一条tcp连接.也就是connection.一旦tcp连接建立起来,客户端就可以创建一个AMQP信道,即channel,每个channel都会被指派一个唯一id.信道是建立在channel之上的虚拟连接.
为什么要引入信道:如果对于每个线程,都建立tcp连接,对于操作系统而言,开销过于昂贵.RabbitMQ使用类似NIO的做法,将tcp连接复用.
每个线程把持一个信道,信道复用了tcp的连接.同时RabbitMQ可以保证每个线程的私密性.就像拥有独立连接一样.当每个信道流量不是很大时,复用连接可以有效节省tcp连接资源.然而当信道本身流量很大时,多个信道复用一个connection就会产生性能瓶颈.进而使整体的流量被限制.这时需要开辟多个connection.将信道分摊到这些connection中.