“ 本文主要介绍RabbitMQ的基础概念,不涉及深层次的概念解析,适合作为RabbitMQ新手指引。”

01 连接Connection
即为socket连接,封装了socket协议相关部分逻辑。
02 通道 Channel
通道是与Rabbitmq打交道最重要的一个接口,大部分业务操作是在Channel接口中完成,包括定义Exchange、Queue、绑定Queue与Exchange、发布消息等。
03 交换器 Exchange
生产者并不是直接把消息发送到消费者queue中,而是先发送到交换器这个“站点”进行汇集,然后再中转到消费者queue中。
exchange的类型有四类:fanout、direct、topic、header。
fanout 扇出型

pub/sub模式。交换器把消息发送到所有与之绑定的queue,该类型交换器很适合做广播业务。
direct 直接型

routing模式。精确的路由模式,直接对比路由键和绑定键,如果routing key和binding key完全相同,则将消息发送到binding key对应的queue中。
topic 模式匹配型

与直接匹配相对应,可以用一些模式来代替字符串的完全匹配。
规则:
以 ‘.’ 来分割单词。
‘#’ 表示一个或多个单词。
‘*’ 表示一个单词。
如:
RoutingKey为:
aaa.bbb.ccc
BindingKey可以为:
*.bbb.ccc
aaa.#
header 类型
headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。
在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。
(header用得比较少)
04 队列 Queue

队列是Rabbitmq的内部对象,用于存储消息。
05 消息回执
Message Acknowledge
在实际应用中,可能会发生消费者收到Queue中的消息,但没有处理完成就宕机(或出现其它意外的情况),在这种情况下就可能会导致消息丢失。为了避免这种情况,我们可以要求消费者在消费完消息后发送 一个回执给RabbitMQ,RabbitMQ收到消息回执(Message Acknowledgement)后才将消息从Queue中移除;如果RabbitMQ没有收到回执并检测到向消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其它消费者(如果存在多个消费者)进行处理。这里不存在timeout概念,一个消费者处理消息的时间再长也不会导致该消息被发送给其它消费者,除非他的RabbitMQ连接断开。
这里会产生另外一个问题,如果我们的开发人员在处理完业务逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug——Queue中堆积的消息会越来越多;消费者重启后会重复消费这些消息,并重复执行业务逻辑。
(对于单个消费者的场景,如果在处理完业务逻辑后,意外宕机,未发送回执,会导致消费者重新启动以后,重复处理该消息,因此,在业务逻辑层面,应该要兼容这种场景,处理消息逻辑考虑幂等性)。
06 消息持久化
Message Durability
如果希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下,Rabbit
MQ的消息不会丢失。但依然解决不了小概率丢失时间的发生(比如RabbitMQ服务器已经接受到生产者的消息,但还没来得及持久化该消息时RabbitMQ服务器就断电了),如果我们需要对这种小概率事件也要管理起来,那么要用到事务。
07 预存取 Prefetch Count
如果多个消费者共同订阅一个Queue中的消息,Queue中的消息会被平摊给多个消费者。这时,如果每个消息的处理时间不同,就有可能会导致某些消费者一直在忙,有些消费者很快就处理玩手头工作并处于空闲装填的情况。可以通过设置prefetchCount来限制Queue每次发送给消费者的消息数,比如设置prefetchCount=1,则Queue每次给每个消费者发送一条消息;消费者处理完这条消息后,Queue才会再给该消费者发送下一条消息 。
08 路由键 Routing Key
生产者在将消息发送给Exchange时,一般会指定一个routing key,来指定这个消息的路由规则,而这个routing key需要与Exchange Type和binding key联合使用才能最终生效。
在Exchange Type与binding key固定的情况下(在正常使用时一般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange的时候,通过指定routing key来决定消息流向哪里。
09 绑定 Binding

RabbitMQ中通过Binding将Exchange与Queue关联起来,这样RabbitMQ就知道如何正确地将消息路由到指定的Queue了:在绑定(Binding)Exchange与Queue的同时,一般会指定一个binding key;生产者者将消息发送给Exchange时,一般会指定一个routing key,当binding key与routing key匹配时,消息将会被路由到对应的Queue中。
在绑定多个Queue到同一个Exchange的时候,这些Binding允许使用相同的binding key。binding key并不是在所有情况下都生效,它依赖于Exchange Type,比如fanout类型的Exchange会无视binding key,而是将消息路由到所有绑定到该Exchange的Queue。
10 RPC

MQ本身是基于异步的消息处理,但实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后再进行下一步处理。这相当于RPC。在RabbitMQ中也支持RPC。
RabbitMQ中实现RPC的机制是:
1、客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置两个值replyTo(一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和correlationId(此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解那条请求被成功执行了或执行失败)。
2、服务器端收到消息并处理。
3、服务器端处理完消息以后,将生成一条应答消息到reply指定的Queue,同时带上correlationId属性。
4、客户端之前已经订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析那条请求被执行了,根据执行结果进行后续业务处理。
11 多租户 multi-tenant
RabbitMQ支持多租户技术,每一个租户表示为一个vhost,其本质上是一个独立的小型RabbitMQ服务器,又有自己独立的队列、交换器及绑定关系等,并且它拥有自己独立的权限。vhost就像是物理机中的虚拟机一。




