联邦队列
概述
本指南介绍了联邦队列,它是 联邦插件 提供的一部分功能。
涵盖的一些主题包括:
另外还有一个 联邦插件参考 指南可用。
除了 联邦交换器,RabbitMQ 还支持联邦队列。此功能提供了一种跨节点或集群来平衡单个逻辑队列负载的方法。它通过在本地队列没有消费者时将消息移动到其他联邦对等节点(节点或集群)来实现。
虽然联邦交换器会将其消息流从上游复制到一个或多个下游,但联邦队列会将数据移动到有消费者的位置,始终优先本地消费者而非远程消费者。联邦队列被视为对等节点,它们之间没有像联邦交换器那样的“主/从”关系。
联邦队列链接到其它的联邦对等队列(称为上游队列)。它将从上游队列检索消息,以满足本地消费者的消息需求。上游队列无需重新配置。假定它们位于单独的节点或单独的集群中。
上游定义是一个 URI,带有控制链接连接参数的特定识别查询参数。可以使用 CLI 工具 或 HTTP API 结合 一个附加插件 来管理上游。
下图演示了在两个使用队列联邦连接的 RabbitMQ 节点中的几个联邦和非联邦队列。

使用队列联邦时,通常只对集群中的一部分队列进行联邦。有些队列可能是“站点”(集群)及其用途的固有本地队列。
用例
典型用法是将同一个“逻辑”队列分发到多个代理。每个代理将声明一个联邦队列,并将所有其他联邦队列作为上游。链接将在联邦对等节点(节点或集群)上形成一个完整的双向图。
这种逻辑分布式队列比单个队列具有更高的容量。当存在一定程度的本地性时,它的性能最佳;即,尽可能多的消息在其发布时就被同一队列消费,并且联邦机制只需要移动消息来进行负载均衡。
运行不同版本 RabbitMQ 的代理可以使用联邦进行连接。
队列联邦也是 蓝绿部署 的重要组成部分,例如 从 RabbitMQ 3.x 迁移到 4.x。
限制
与非联邦队列以及联邦交换器相比,联邦队列包含一些限制或差异。
队列联邦不会将 绑定 从下游传播到上游。
使用 basic.get(通过轮询消费,一种强烈不推荐的做法)的应用程序无法通过联邦检索消息,如果本地队列(客户端连接到的节点上的队列)中没有消息的话。由于 basic.get 是一个同步方法,处理请求的节点将不得不阻塞,同时联系所有其他节点以检索更多消息。这不符合联邦的可用性和分区容错导向的设计和用例。
用法和配置
联邦队列就像任何其他队列一样,由应用程序声明。为了让 RabbitMQ 识别一个队列需要被联邦,以及应该从哪些其他节点消费消息,需要配置下游(消费)节点。

联邦配置使用 运行时参数和策略,这意味着它可以根据系统拓扑变化即时配置和重新配置。涉及两个关键配置项:
- 上游:这些是联邦系统中的远程端点。
- 联邦策略:这些控制哪些队列被联邦以及它们将连接到哪些上游(对等节点)。
这两者都配置在下游节点或集群上。
要添加上游,请使用 rabbitmqctl set_parameter 命令。它接受三个参数:
- 参数类型,
federation-upstream - 一个上游名称,联邦策略将引用它。
- 一个上游定义 JSON 文档,至少包含一个必需的键,
uri。
以下示例配置了一个名为“origin”的上游,可以通过 remote-host.local:5672 联系到它。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
# Adds a federation upstream named "origin"
rabbitmqctl set_parameter federation-upstream origin '{"uri":"amqp://remote-host.local:5672"}'
# Adds a federation upstream named "origin"
rabbitmqadmin federation declare_upstream_for_queues --name origin \
--uri "amqp://remote-host.local:5672"
# Adds a federation upstream named "origin"
rabbitmqctl.bat set_parameter federation-upstream origin '"{""uri"":""amqp://remote-host.local:5672""}"'
# Adds a federation upstream named "origin"
rabbitmqadmin.exe federation declare_upstream_for_queues --name origin ^
--uri "amqp://remote-host.local:5672"
指定上游后,可以添加一个控制联邦的策略。它就像任何其他 策略 一样添加,使用 rabbitmqctl set_policy。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
# Adds a policy named "queue-federation"
rabbitmqctl set_policy queue-federation "^federated\." \
'{"federation-upstream-set":"all"}' \
--priority 10 \
--apply-to queues
# Adds a policy named "queue-federation"
rabbitmqadmin policies declare \
--name "queue-federation" \
--pattern "^federated\." \
--definition '{"federation-upstream-set":"all"}' \
--priority 10 \
--apply-to "queues"
# Adds a policy named "queue-federation"
rabbitmqctl.bat set_policy queue-federation '^federated\.' `
'"{""federation-upstream-set"":""all""}"' `
--priority 10 `
--apply-to queues
# Adds a policy named "queue-federation"
rabbitmqadmin.exe policies declare ^
--name "queue-federation" ^
--pattern "^federated\." ^
--definition "{""federation-upstream-set"":""all""}" ^
--priority 10 ^
--apply-to "queues"
在上面的示例中,该策略将匹配在默认虚拟主机中名称以 federated. 前缀开头的队列。这些队列将为所有声明的上游设置联邦链接。策略的名称是 queue-federation。与任何策略一样,如果多个策略匹配一个队列,则优先级最高的策略将被使用。即使优先级相等,多个策略定义也不会合并。
配置完成后,将为每个匹配的队列和上游对打开一个联邦链接(连接)。这里的“匹配队列”是指被 联邦策略模式 匹配的队列。如果没有匹配的队列,将不会启动任何链接。
要为匹配的队列停用联邦,请使用策略名称删除该策略。
rabbitmqctl clear_policy queue-federation
复杂拓扑和循环处理
一个联邦队列可以成为另一个联邦队列的“上游”。甚至可以形成“循环”,例如,队列 A 将队列 B 声明为其上游,队列 B 将队列 A 声明为其上游。允许更复杂的多个连接的排列。然而,这种复杂的拓扑将越来越难以理解和排查。
与联邦交换器不同,队列联邦不复制数据,也不显式处理循环。消息在联邦队列之间转发的次数没有限制。
在一组相互联邦的队列中,消息将移动到有空闲消费能力的位置,因此如果空闲消费能力不断移动,消息也会移动。由于消息仅在本地没有消费者时才移动到远程节点,因此消息很少会跨所有节点“绕一圈”。
实现
联邦队列将使用 AMQP 0-9-1 连接到所有上游队列(可以选择 使用 TLS 进行安全连接)。
联邦队列仅在本地消息耗尽、有需要消息的消费者以及上游队列有“空闲”的、未被消费的消息时才会检索消息。目的是确保消息仅在需要时才在联邦队列之间传输。这是通过 消费者优先级 来实现的。
如果消息从一个队列转发到另一个队列,那么消息顺序仅对经过完全相同节点路径的消息有效。在某些情况下,当发布时相邻的消息可能会采取不同的路径到达同一节点进行消费;因此,在存在队列联邦的情况下,消息可能会被重新排序。
每个单独的队列独立应用其参数;例如,如果您在联邦队列上设置了 x-max-length,那么该队列的长度将受到限制(可能在满时丢弃消息),但与其联邦的其他队列将不受影响。请特别注意,在使用 每个队列或每条消息的 TTL 时,消息在传输到另一个队列时其计时器会重置。
陷阱
联邦队列目前无法仅基于在一个地方需要消息来导致消息在代理之间进行多次跳跃。例如,如果您在节点 A、B 和 C 上联邦队列,A 和 B 连接,B 和 C 连接,但 A 和 C 不连接,那么如果 A 上有消息并且 C 上有消费者等待,消息不会通过 B 从 A 传输到 C,除非 B 上也有一个消费者。
可以将联邦队列绑定到联邦交换器。但是,结果可能与某些人预期的不同。由于联邦交换器将根据其绑定从上游检索消息,任何发布到联邦交换器的消息都将被复制到具有匹配绑定的任何节点。然后,联邦队列将在节点之间移动这些消息,因此可能会在同一节点上出现同一消息的多个副本。