Message Queue
(MQ
)消息队列中间件,通常我们在网上看到的对其定义是将消息的发送和接受分离来实现应用程序的异步和解耦,给人的直觉是 MQ
是异步的,用来解耦的。但这个只是 MQ
的效果,而不是目的。MQ
真正的目的是为了通讯,屏蔽底层复杂的通讯协议,定义了一套应用层上更加简单的通讯协议。
一套分布式系统中两个模块之间通讯要么是 HTTP
,要么是 TCP
,但这两种协议其实都是原始的协议。前者实现通讯就必须要做到各客户端都有 WebServer
,而且不支持长连接;后者就更加原始了 — 粘包、心跳、私有的协议。
而 MQ
所要做就是在基于这些现有的协议之上构建一个更简单的通讯(生产者/消费者)模型。它定义了两个对象 —发送数据的叫生产者,接受数据的叫消费者,提供一个 SDK 给我们自己定义生产者和消费者实现消息通讯,且无视底层通讯协议。
这个流派通常有一台服务器作为 Broker
,所有的消息都通过它进行中转。生产者把消息发送给它就结束自己的任务了,最后 Broker
则把消息主动推送给消费者(或者消费者主动轮询)。
Kafka
、Active MQ
就属于这个流派:生产者发送 key
和数据到 Broker
,由 Broker
比较 key
之后决定给哪个消费者。
在这种模式下,Topic(主题消息)
往往是一个比较大的概念,甚至一个系统中就可能只有一个 Topic
。
虽然这两种消息队列的架构一样,但是 Kafka
的性能要比 Active MQ
的性能不知道高到多少倍,所以基本这种类型的 MQ
只有 Kafka
一种备选方案。
这种的代表是 RabbitMQ
(AMQP
)。生产者发送 key
和数据,Borker
收到数据之后会根据 key
通过一定的逻辑计算出相应的队列,最后消费者订阅队列。
在这种架构中 Queue
是非常轻量级的(在 RabbitMQ
中它的上限取决于你的内存),消费者关心的只是自己的 Queue
;生产者不必关心数据最终给谁,只要指定 key
就行了。中间的那层映射在 AMQP
中叫 exchange(交换机)
。
AMQP
中有四种 exchange
:
Direct exchange
:key
等于 queue
。
Fanout exchange
:无视 key
,给所有的 queue
都来一份。
Topic exchange
:key
可以用 “宽字符” 模糊匹配 queue
。
Headers exchange
:无视 key
,通过查看消息的头部元数据来决定发给哪个 queue
。
这种架构给通讯带来了极大的灵活性,我们能想到的通讯方式都可以用这四种 exchange
表达出来。
不带 Broker
的 MQ
代表就是 ZeroMQ
。可以说是解决通讯问题的更高级 Socket
,它被设计成了一个 “库” 而不是一个中间件,这种实现也可以达到没有 Broker
的目的。
各节点之间的通讯都是发送到彼此的队列中,每个节点即是生产者也是消费者。类似于一套 Socket
的 API
,可以完成发送和读取数据。
文章作者:彭超
本文首发于个人博客:https://antoniopeng.com/2020/06/15/mq/%E8%B0%88%E8%B0%88%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84%E6%B5%81%E6%B4%BE/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 彭超 | Blog!