交换机和队列的联邦
本指南涵盖了与集群联邦相关的各种主题,包括交换机和队列的联邦。
概述
联邦插件的宏观目标是在启用了该插件但不同属于同一集群的代理之间复制或移动消息。这在很多方面都很有用。
节点或集群的松耦合
联邦插件可以在不同管理域中的代理(或集群)之间传输消息。
- 它们可能托管在不同的数据中心,可能位于不同的大陆。
- 它们可能有不同的用户、虚拟主机、权限和用途。
- 它们可能运行在不同版本的 RabbitMQ 和 Erlang 上。
- 它们可能大小不同。
WAN 友好性
联邦插件的通信完全是异步的,并假设集群之间的连接会时断时续。因此,它很好地容忍了间歇性的连接,并且不会在远程集群之间(在可用性方面)造成耦合。
特异性
代理可以包含联邦和本地专用的组件,以最佳地适应系统的期望架构。
随着连接节点数量的增长而扩展
联邦不需要N个代理之间的 O(n2) 连接(尽管这是最简单的设置方式)。
它做什么?
联邦插件使得可以联邦交换机和队列。联邦交换机或队列可以从一个或多个称为上游的远程集群接收消息(更准确地说:存在于远程集群中的交换机和队列)。
一个联邦交换机会“重放”发布到其对应上游的消息流,并将它们发布到本地队列或流。
联邦队列允许本地消费者在远程队列本身没有本地消费者在线时接收来自上游队列的消息。
联邦链接连接到上游的方式与应用程序连接大致相同。因此,它们可以连接到特定的 vhost,使用 TLS,使用多个 认证机制。
通常,联邦用于连接远程集群。但是,它也可以用于移动同一集群内 虚拟主机之间的数据。
联邦文档组织成一系列更集中的指南。
如何设置联邦?
设置联邦涉及两个步骤。
- 首先,必须定义一个或多个上游。它们为联邦提供有关如何连接到其他节点的信息。这可以通过 运行时参数 或 联邦管理插件 来完成,该插件为 管理 UI 添加了一个联邦管理选项卡。
- 要启用联邦,必须声明一个或多个匹配交换机或队列的 策略。该策略将使匹配的对象(例如交换机)被联邦化,并且每个匹配都会启动一个联邦链接(与其他节点的连接)。
入门
联邦插件包含在 RabbitMQ 发行版中。要启用它,请使用 rabbitmq-plugins。
rabbitmq-plugins enable rabbitmq_federation
如果使用 管理 UI,则建议同时启用 rabbitmq_federation_management。
rabbitmq-plugins enable rabbitmq_federation_management
在集群中使用联邦时,集群的所有节点都应启用联邦插件。
有关联邦上游的信息与用户、权限、队列等一起存储在 RabbitMQ 数据库中。联邦涉及三个配置级别。
- 上游:每个 上游 定义一个远程连接端点。
- 上游集:每个 上游集将一组上游分组 以用于联邦。
- 策略:每个 策略选择一组交换机、队列或两者,并将单个上游或上游集应用于这些对象。
实际上,对于简单的用例,您可以几乎忽略上游集的存在,因为有一个隐含定义的名为 all 的上游集,所有上游都添加到其中。
上游和上游集都使用 运行时参数 定义。与交换机和队列一样,每个虚拟主机都有自己独特的一组参数和策略。有关参数和策略的更通用信息,请参阅 参数和策略 指南。有关联邦使用的参数的完整详细信息,请参阅 联邦参考。
参数和策略可以通过三种方式设置。
- 使用 CLI 工具。
- 如果启用了扩展插件(
rabbitmq_federation_management),则在管理 UI 中。 - 使用 HTTP API。
HTTP API 有一个限制:它不支持上游集的管理。
一个基本示例
这里我们将联邦所有内置交换机(除了默认交换机)到一个上游。该上游将配置为在断开连接时最多缓冲消息一小时(3600000 毫秒)。
要定义上游,请使用以下示例之一,每个选项卡一个。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
- Management UI
- HTTP API
# target.hostname is just an example, replace it with a URI
# of the target node (usually a member of a remote node/cluster,
# or a URI that connects to a different virtual host within the same cluster)
rabbitmqctl set_parameter federation-upstream my-upstream \
'{"uri":"amqp://target.hostname","expires":3600000}'
# target.hostname is just an example, replace it with a URI
# of the target node (usually a member of a remote node/cluster,
# or a URI that connects to a different virtual host within the same cluster)
rabbitmqadmin federation declare_upstream --name my-upstream \
--uri "amqp://target.hostname" \
--ttl 3600000
# target.hostname is just an example, replace it with a URI
# of the target node (usually a member of a remote node/cluster,
# or a URI that connects to a different virtual host within the same cluster)
rabbitmqctl.bat set_parameter federation-upstream my-upstream `
'"{""uri"":""amqp://target.hostname"",""expires"":3600000}"'
# target.hostname is just an example, replace it with a URI
# of the target node (usually a member of a remote node/cluster,
# or a URI that connects to a different virtual host within the same cluster)
rabbitmqadmin.exe federation declare_upstream --name my-upstream ^
--uri "amqp://target.hostname" ^
--ttl 3600000
导航到 Admin > Federation Upstreams > Add a new upstream。在 Name 处输入“my-upstream”,在 URI 处输入“amqp://target.hostname”,在 Expiry 处输入 36000000。单击 Add upstream。
PUT /api/parameters/federation-upstream/%2f/my-upstream
{"value":{"uri":"amqp://target.hostname","expires":3600000}}
然后定义一个匹配内置交换机并使用此上游的策略。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
- Management UI
- HTTP API
rabbitmqctl set_policy --apply-to exchanges federate-me "^amq\." \
'{"federation-upstream-set":"all"}'
rabbitmqadmin policies declare \
--name "federate-me" \
--pattern "^amq\." \
--definition '{"federation-upstream-set":"all"}' \
--apply-to "exchanges"
rabbitmqctl.bat set_policy --apply-to exchanges federate-me "^amq\." `
'"{""federation-upstream-set"":""all""}"'
rabbitmqadmin.exe policies declare ^
--name "federate-me" ^
--pattern "^amq\." ^
--definition "{""federation-upstream-set"":""all""}" ^
--apply-to "exchanges"
导航到 Admin > Policies > Add / update a policy。在“Name”处输入“federate-me”,在“Pattern”处输入“^amq.”,从“Apply to”下拉列表中选择“Exchanges”,并在“Policy”旁边的第一行输入“federation-upstream-set” = “all”。单击 Add policy。
PUT /api/policies/%2f/federate-me
{"pattern":"^amq\.", "definition":{"federation-upstream-set":"all"}, "apply-to":"exchanges"}
定义的策略将使名称以“amq.”开头的所有内置交换机(默认交换机除外)以(隐式的)低优先级进行联邦,并使用隐式创建的上游集“all”进行联邦,该上游集包括我们新创建的上游。
任何其他具有大于 0 的优先级的匹配策略将优先于此策略。请记住,federate-me 只是我们在此示例中使用的名称,您可以在那里使用任何您想要的字符串。
内置交换机现在应该被联邦化,因为它们被策略匹配。您可以通过在管理界面中检查交换机列表或使用以下命令来验证策略是否已应用于交换机。
rabbitmqctl list_exchanges name policy | grep federate-me
您可以通过导航到 Admin > Federation Status > Running Links 或使用以下命令来检查每个交换机的联邦链接是否已建立。
# This command will be available only if federation plugin is enabled
rabbitmqctl federation_status
一般来说,每个应用于交换机的上游都会有一个联邦链接。例如,如果有三个交换机和两个上游,将会有六个链接。
对于简单用例,这应该就是您所需的一切——您可能需要查看 AMQP URI 参考。
《联邦参考》包含有关上游参数和上游集的更多详细信息。
联邦连接(链接)故障
联邦使用的节点间连接基于 AMQP 0-9-1 连接。运维人员可以将联邦链接视为一种特殊的客户端。
如果链接失败,例如由于网络中断,它将尝试重新连接。重新连接周期是在上游定义中配置的值。有关设置上游和上游集的更多详细信息,请参阅 联邦参考。
链接通常会尝试无限期地恢复,但也有它们会放弃的情况。
- 失败率过高(可容忍的最大速率取决于上游的
reconnect-delay,但通常默认为每隔几秒钟一次)。 - 链接不再能找到其“源”队列或交换机。
- 策略发生变化,以至于链接认为自己不再需要了。
通过增加上游的 reconnect-delay,可以容忍更高的链接失败率。这主要与 RabbitMQ 安装相关,这些安装具有中等或大量活动链接。
联邦集群
集群可以像单个代理一样通过联邦链接在一起。总结一下集群和联邦的交互方式。
- 您可以在下游集群的任何节点上定义策略和参数;一旦在一个节点上定义,它们将应用于所有节点。
- 交换机联邦链接将在下游集群的任何节点上启动。如果运行它们的节点崩溃或停止,它们将故障转移到其他节点。
- 队列联邦链接将在与下游队列相同的节点上启动。如果下游队列是复制的队列,它们将在领导者所在的节点上启动,并在任何将来的领导者选举后在新的领导者所在的节点上重新创建。
- 要连接到上游集群,您可以在单个上游中指定多个 URI。联邦链接进程将在每次尝试连接时随机选择这些 URI 之一。
使用 TLS 保护联邦连接
从 Erlang 26 开始,TLS 实现默认启用TLS 客户端对等方验证。
如果未配置客户端 TLS 证书和密钥对,启用了 TLS 的联邦链接将无法连接。对于需要使用对等验证的启用了 TLS 的联邦链接,必须配置证书(公钥)和私钥对。
如果不需要对等验证,可以禁用它。
联邦连接(链接)可以使用 TLS 进行保护。因为联邦在底层使用 RabbitMQ 客户端,所以有必要同时配置目标代理以 监听 TLS 连接,并配置联邦使用 TLS。
要配置联邦使用 TLS,需要。
- 在 upstream URI 中,使用
amqps作为方案而不是amqp,并使用端口5671而不是5672(假设使用默认端口,但显式指定了端口)。 - 在同一个 upstream URI 中,通过 URI 查询参数指定 CA 证书和客户端证书/密钥对,以及其他参数(特别是 启用或禁用对等验证、对等验证深度)。
- 可选地,通过 Erlang 客户端设置配置 与 TLS 相关的 设置或所有链接的通用默认值(外加,可选地,Shovel)。
在下面的示例中,修改了 upstream URI 以使用 TLS 和客户端证书(公钥)以及私钥对,但禁用了对等验证(为简单起见,建议在生产环境中使用)。
- 使用 rabbitmqctl (bash)
- 使用 rabbitmqadmin (bash)
- 使用 rabbitmqctl (PowerShell)
- 使用 PowerShell 的 rabbitmqadmin.exe
- Management UI
- HTTP API
# Note the TLS-related settings in the upstream URI field
rabbitmqctl set_parameter federation-upstream my-upstream \
'{"uri":"amqps://target.hostname:5671?cacertfile=/path/to/ca_bundle.pem&certfile=/path/to/client_certificate.pem&keyfile=/path/to/client_key.pem&verify=verify_none","expires":3600000}'
# Note the TLS-related settings in the upstream URI field
rabbitmqadmin federation declare_upstream --name my-upstream \
--uri "amqps://target.hostname:5671?cacertfile=/path/to/ca_bundle.pem&certfile=/path/to/client_certificate.pem&keyfile=/path/to/client_key.pem&verify=verify_none" \
--ttl 3600000
#
rabbitmqctl.bat set_parameter federation-upstream my-upstream `
'"{""uri"":""amqps://target.hostname:5671?cacertfile=drive:\path\to\ca_bundle.pem&certfile=drive:\path\to\client_certificate.pem&keyfile=drive:\path\to\client_key.pem&verify=verify_none"",""expires"":3600000}"'
# Note the TLS-related settings in the upstream URI field
rabbitmqadmin.exe federation declare_upstream --name my-upstream ^
--uri "amqps://target.hostname:5671?cacertfile=drive:\path\to\ca_bundle.pem&certfile=drive:\path\to\client_certificate.pem&keyfile=drive:\path\to\client_key.pem&verify=verify_none" ^
--ttl 3600000
导航到 Admin > Federation Upstreams > Add a new upstream。在 Name 处输入“my-upstream”,在 URI 处粘贴 "amqps://target.hostname:5671?cacertfile=/path/to/ca_bundle.pem&certfile=/path/to/client_certificate.pem&keyfile=/path/to/client_key.pem&verify=verify_none",然后在 Expiry 处输入 36000000。
单击 Add upstream。
PUT /api/parameters/federation-upstream/%2f/my-upstream
{"value":{"uri":"amqps://target.hostname:5671?cacertfile=/path/to/ca_bundle.pem&certfile=/path/to/client_certificate.pem&keyfile=/path/to/client_key.pem&verify=verify_none","expires":3600000}}
这些示例使用了带有四个附加 URI 查询参数的 URI。
cacertfile:CA 证书捆绑文件,其中包含一个或多个用于签署客户端证书和私钥对的 CA 证书。certfile:客户端证书(公钥)。keyfile:客户端私钥。verify:控制对等验证(在此特定示例中,禁用它)。
与“常规”客户端连接一样,如果启用了 TLS 的联邦链接需要执行对等验证,则服务器的 CA 必须在运行联邦链接的节点上受信任,反之亦然。
联邦链接监控
每个联邦交换机或队列与上游的组合都需要一个链接来运行。这是检索消息并将其重新发布到下游的过程。您可以使用 rabbitmqctl 和管理插件监控联邦链接的状态。
使用 CLI 工具
可以使用 RabbitMQ CLI 工具检查联邦链接状态。
调用
# This command will be available only if federation plugin is enabled
rabbitmqctl federation_status
这将输出目标节点上(而不是集群范围)运行的联邦链接列表。它包含以下键。
| 参数名称 | 描述 |
type |
|
name | 联邦交换机或队列的名称。 |
vhost | 包含联邦交换机或队列的虚拟主机。 |
upstream_name | 此链接连接到的上游的名称。 |
status | 链接的状态。
|
connection | 此链接的连接名称(来自配置)。 |
timestamp | 上次状态更新的时间戳。 |
这是一个例子。
# This command will be available only if federation plugin is enabled
rabbitmqctl federation_status
# => [[{type,<<"exchange">>},
# => {name,<<"my-exchange">>},
# => {vhost,<<"/">>},
# => {connection,<<"upstream-server">>},
# => {upstream_name,<<"my-upstream-x">>},
# => {status,{running,<<"<rabbit@my-server.1.281.0>">>}},
# => {timestamp,{{2020,3,1},{12,3,28}}}]]
# => ...done.
使用管理 UI
启用 rabbitmq_federation_management 插件,该插件扩展了 管理 UI,使其具有一个新页面,显示集群中的联邦链接。它可以在 Admin > Federation Status 下找到,或者使用 GET /api/federation-links HTTP API 端点。
故障排除
联邦链接未启动
联邦链接在以下情况下启动。
- 存在已配置的上游(或一组上游)。
- 存在匹配某些交换机或队列的策略。
- 联邦能够连接到目标上游。
因此,为了缩小问题范围,建议的步骤是。
检查联邦上游
- 使用 bash 的 rabbitmq-diagnostics
- 使用 rabbitmqadmin (bash)
- 使用 PowerShell 的 rabbitmq-diagnostics
- 使用 PowerShell 的 rabbitmqadmin.exe
- Management UI
- HTTP API
rabbitmq-diagnostics list_parameters --formatter=pretty_table
rabbitmqadmin federation list_all_upstreams
rabbitmq-diagnostics.bat list_parameters --formatter=pretty_table
rabbitmqadmin.exe federation list_all_upstreams
确保已启用 rabbitmq_federation_management 插件。
导航到 Admin > Federation Upstreams。
GET /api/parameters
检查策略
在 RabbitMQ 中一次只能应用一个策略,并且在 N 个具有相同优先级的策略中会随机选择一个。
换句话说,当存在匹配要联邦的交换机或队列的冲突策略时,不能保证启用联邦的策略是有效的。
使用明确不同的策略并避免 --apply-to all 的策略将降低遇到此问题的风险。