RabbitMQ
是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是使用Erlang(高并发语言)语言来编写的,并且RabbitMQ是基于AMQP协议的
AMQP协议
Advanced Message Queuing Protocol(高级消息队列协议),具有现代特征的二进制协议,是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息中间件设计
AMQP专业术语
- Productor:消息的生产者,也是一个向交换器发布消息的客户端应用程序
- Consumer:消息的消费者,表示一个从消息队列中取得消息的客户端应用程序
- Queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走
- Message:消息,服务器与应用程序之间传送的数据,由Properties和Body组成.Properties可以对消息进行修饰,必须消息的优先级、延迟等高级特性;Body则是消息体内容
- Broker:接受客户端的链接,接收和分发消息的应用
- Connection:publisher/consumer 和 broker 之间的 TCP 连接
- Channel:网络信道,几乎所有的操作都在channel中进行,Channel是进行消息读写的通道。客户端可以建立多个channel,每个channel代表一个会话任务
- Virtual Host:虚拟地址,用于进行逻辑隔离,最上层的消息路由。一个virtual host里面可以有若干个Exchange和Queue,同一个Virtual Host 里面不能有相同名称的Exchange 或 Queue
- Exchange:交换机,接收消息,根据路由键转单消息到绑定队列
- Binding:Exchange和Queue之间的虚拟链接,binding中可以包换routing key
- Routing key:一个路由规则,虚拟机可用它来确定如何路由一个特定消息。(如负载均衡)
提示
Exchange和队列是多对多关系,实际操作一般为1个exchange对多个队列,为避免设计过于复杂
Channel多路复用
RabbitMQ的多路复用与IO多路复用类似,RabbitMQ是利用Channel做多路复用,来应对高并发的。
IO多路复用,详见博文:博文链接
RabbitMQ六种队列模式
简单队列模式
最简单的工作队列,其中一个消息生产者(P),一个消息消费者(C),一个队列。也称为点对点模式
工作队列
一个消息生产者,一个交换器,一个消息队列,多个消费者。同样也称为点对点模式
工作队列:用来将耗时的任务分发给多个消费者(工作者)
发布订阅
将消息发送给不同类型的消费者。做到发布一次,多个消费者来消费。
路由模式
在发布/订阅模式的基础上,有选择的接收消息,也就是通过 routing 路由进行匹配条件是否满足接收消息
上图是一个结合日志消费级别的配图,在路由模式它会把消息路由到那些 binding key 与 routing key 完全匹配的 Queue 中,此模式也就是 Exchange 模式中的direct
模式。
以上图的配置为例,我们以 routingKey=“error” 发送消息到 Exchange,则消息会路由到Queue1(amqp.gen-S9b…,这是由RabbitMQ自动生成的Queue名称)和Queue2(amqp.gen-Agl…)
如果以 routingKey=“info” 或 routingKey=“warning” 来发送消息,则消息只会路由到 Queue2
如果以其他 routingKey 发送消息,则消息不会路由到这两个 Queue 中
主题模式
同样是在发布/订阅模式的基础上,根据主题匹配进行筛选是否接收消息。topics 主题模式跟 routing 路由模式类似,只不过路由模式是指定固定的路由键 routingKey,而主题模式是可以模糊匹配路由键routingKey,类似于SQL中 = 和 like 的关系。
topics 模式与 routing 模式比较相近,topics 模式不能具有任意的 routingKey,必须由一个英文句点号.
(点)分隔的字符串(将被句点号.
分隔开的每一段独立的字符串称为一个单词),比如 “lazy.orange.fox”。topics routingKey 中可以存在两种特殊字符*
(星号)与#
(井号),用于做模糊匹配,其中*
(星号)用于匹配一个单词,#
(井号)用于匹配多个单词(可以是零个)
*
表示任何一个词#
表示0或多个词
以上图中的配置为例:
- 如果一个消息的 routingKey 设置为 “xxx.orange.rabbit”,那么该消息会同时路由到 Q1 与 Q2,
- routingKey=“lazy.orange.fox” 的消息会路由到Q1与Q2
- routingKey=“lazy.brown.fox” 的消息会路由到 Q2
- routingKey=“lazy.pink.rabbit” 的消息会路由到 Q2(只会投递给Q2一次,虽然这个routingKey 与 Q2 的两个 bindingKey 都匹配)
- routingKey=“quick.brown.fox”、routingKey=“orange”、routingKey=“quick.orange.male.rabbit” 的消息将会被丢弃,因为它们没有匹配任何bindingKey
RPC模式
与上面其他5种所不同之处,RPC模式是拥有请求/回复的
RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据
RPC的处理流程:
- 当客户端启动时,创建一个匿名的回调队列
- 客户端为RPC请求设置2个属性:replyTo,设置回调队列名字;correlationId,标记request
- 请求被发送到rpc_queue队列中
- RPC服务器端监听rpc_queue队列中的请求,当请求到来时,服务器端会处理并且把带有结果的消息发送给客户端。接收的队列就是replyTo设定的回调队列
- 客户端监听回调队列,当有消息时,检查correlationId属性,如果与request中匹配,那就是结果了