分布式 RabbitMQ
概述
AMQP 0-9-1、AMQP 1.0 以及 RabbitMQ 通过插件支持的其他消息协议(如 STOMP),(当然)本质上就是分布式的:应用程序几乎总是连接到远程主机上的 RabbitMQ。
通常情况下,有必要或期望使 RabbitMQ 代理(broker)本身也实现分布式。实现这一目标有三种方式:使用集群(Clustering)、联合(Federation)以及使用 Shovel 插件。本页面概述了每种方法。
请注意,这三种方法并不互斥,可以结合使用:集群可以通过联合或 Shovel 连接在一起,也可以两者并用。
集群(Clustering)
集群将多台机器连接在一起以形成一个集群。节点间的通信对客户端是透明的。集群设计的前提是网络连接相对可靠,并提供类似局域网(LAN)的延迟。
集群中的所有节点必须运行兼容版本的 RabbitMQ 和 Erlang。
节点之间使用预共享密钥进行身份验证,该密钥通常由部署自动化工具安装。
虚拟主机、交换器、用户和权限会在集群中的所有节点间自动复制。队列可以位于单个节点上,也可以复制其内容以实现更高的可用性。仲裁队列(Quorum queues)是一种侧重于数据安全的现代复制队列类型。流(Streams)是另一种允许重复消费(读取)的复制消息数据类型。
连接到集群中任一节点的客户端可以使用集群中所有的非独占队列,即使这些队列并不位于该节点上。
集群节点有助于提高可用性、队列数据安全性,并支持更多的并发客户端连接。集群、仲裁队列和流指南提供了关于这些主题的更多详细信息。
联合(Federation)
联合允许一个代理上的交换器或队列接收发送到另一个代理(这些代理可以是独立的机器,也可以是集群)的交换器或队列上的消息。通信通过 AMQP(可选 SSL)进行,因此为了使两个交换器或队列能够联合,必须授予它们相应的用户权限。
联合交换器通过单向点对点链接连接。默认情况下,消息只会在联合链接上传输一次,但这可以进行调整以允许更复杂的路由拓扑。某些消息可能不会通过该链接转发;如果一条消息在到达联合交换器后无法路由到任何队列,它最初就不会被转发。
联合队列同样通过单向点对点链接连接。为了跟随消费者,消息可以在联合队列之间移动任意多次。
通常,您会使用联合功能来连接跨互联网的代理,以实现发布/订阅消息传递和工作队列处理。
Shovel
使用 Shovel 插件连接代理在概念上与使用联合连接类似。然而,该插件工作在更低的层级。
联合旨在提供一种主观的交换器和队列分布方式,而 Shovel 只是简单地从一个代理的队列中消费消息,并将它们转发到另一个代理的交换器上。
当您需要比联合功能提供更精细的控制时,通常会使用 Shovel 来跨互联网连接代理。
动态 Shovel 对于在单个代理上以临时方式移动消息也很有用。
总结
| 联合和/或 Shovel | 集群 |
|---|---|
代理在逻辑上是独立的,并且可能拥有不同的所有者。 | 集群构成一个单一的逻辑代理。 |
代理可以运行不同(且在某些方面不兼容)版本的 RabbitMQ 和 Erlang。 | 节点必须运行兼容版本的 RabbitMQ 和 Erlang。 |
代理可以通过不可靠的广域网(WAN)链路连接。通信通过 AMQP 0-9-1 进行(可选由 TLS 加密),需要设置适当的用户和权限。 | 代理必须通过相对可靠的局域网(LAN)链路连接。节点将使用共享密钥进行身份验证,并可选择使用启用 TLS 的链路。 |
代理可以按您安排的任何拓扑结构进行连接。链接可以是单向或双向的。 | 所有节点在两个方向上都连接到所有其他节点。 |
强调 CAP 定理中的可用性(Availability)和分区容错性(Partition Tolerance,即 AP)。 | 强调 CAP 定理中的一致性(Consistency)和分区容错性(Partition Tolerance,即 CP)。 |
代理中的某些交换器可以是联合的,而另一些可以是本地的。 | 集群是“全有或全无”的。 |
连接到任一代理的客户端只能使用该代理中的非独占队列。 | 连接到任一节点的客户端可以使用所有节点上的非独占队列。 |