交换器和队列联邦
本指南涵盖了与集群联邦相关的各种主题,包括交换器联邦和队列联邦
概述
联邦插件的高级目标是在启用了该插件但属于不同集群的代理之间复制或移动消息。出于多种原因,这非常有用。
节点或集群的松耦合
联邦插件可以在不同管理域的代理(或集群)之间传输消息
- 它们可能托管在不同的数据中心,甚至可能在不同的大陆上
- 它们可能有不同的用户、虚拟主机、权限和用途
- 它们可能运行在不同版本的 RabbitMQ 和 Erlang 上
- 它们的规模可能不同
广域网 (WAN) 友好性
联邦插件的通信完全是异步的,并假定集群之间的连接会时不时中断。因此,它能很好地容忍间歇性连接,并且不会在远程集群之间(就可用性而言)产生耦合。
特异性
代理可以包含联邦组件和仅本地运行的组件,以最适合系统的预期架构。
随连接节点数量增加的可扩展性
联邦不需要 N 个代理之间存在 O(n2) 的连接(尽管这是设置起来最简单的方法)。
它有什么作用?
联邦插件使得联邦交换器和队列成为可能。联邦交换器或队列可以从一个或多个称为上游 (upstreams) 的远程集群接收消息(更准确地说:存在于远程集群中的交换器和队列)。
联邦交换器会“重放”发布到其上游对应项的消息流,并将它们发布到本地队列或流中。
当远程队列本身没有任何在线的本地消费者时,联邦队列允许本地消费者接收来自上游队列的消息。
联邦链路连接到上游的方式与应用程序连接的方式大致相同。因此,它们可以连接到特定的虚拟主机 (vhost),使用 TLS,并使用多种 身份验证机制。
通常,联邦用于连接远程集群。但是,它也可以用于在同一集群内的 虚拟主机 之间移动数据。
联邦文档被组织为若干更具针对性的指南
如何设置联邦?
设置联邦涉及两个步骤
- 首先,必须定义一个或多个上游。它们为联邦提供有关如何连接到其他节点的信息。这可以通过 运行时参数 或 联邦管理插件 完成,后者会向 管理 UI 添加一个联邦管理选项卡。
- 要启用联邦,必须声明一个或多个与交换器或队列匹配的 策略。策略将使匹配的对象(例如交换器)成为联邦对象,并且对于每个匹配项,都会启动一个联邦链路(到其他节点的连接)。
入门
联邦插件包含在 RabbitMQ 发行版中。要启用它,请使用 rabbitmq-plugins
rabbitmq-plugins enable rabbitmq_federation
如果使用了 管理 UI,建议同时启用 rabbitmq_federation_management
rabbitmq-plugins enable rabbitmq_federation_management
在集群中使用联邦时,集群中的所有节点都应启用联邦插件。
关于联邦上游的信息与用户、权限、队列等一起存储在 RabbitMQ 数据库中。联邦涉及三个配置级别
- 上游 (Upstreams):每个 上游 定义一个远程连接端点。
- 上游集 (Upstream sets):每个 上游集 将一组用于联邦的上游组合在一起。
- 策略 (Policies):每个 策略 选择一组交换器、队列或两者,并将单个上游或上游集应用于这些对象。
在实践中,对于简单的用例,您几乎可以忽略上游集的存在,因为有一个隐式定义的名为 all 的上游集,所有上游都会添加到其中。
上游和上游集均使用 运行时参数 定义。与交换器和队列一样,每个虚拟主机都有自己独特的参数和策略集。有关参数和策略的更多通用信息,请参阅 参数和策略 指南。有关联邦所用参数的完整详细信息,请参阅 联邦参考。
参数和策略可以通过三种方式设置
- 使用 CLI 工具
- 如果启用了扩展插件 (
rabbitmq_federation_management),则在管理 UI 中 - 使用 HTTP API
HTTP API 有一个限制:它不支持上游集的管理。
基础示例
在这里,我们将使用单个上游来联邦除了默认交换器之外的所有内置交换器。该上游定义为在断开连接时最多缓冲消息一小时 (3600000ms)。
要定义上游,请使用以下示例之一(每个选项卡一个)
- 使用 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 安装相关。
联邦集群
集群可以像单个代理一样通过联邦连接在一起。总结集群和联邦的交互方式
- 您可以在下游集群的任何节点上定义策略和参数;一旦在一个节点上定义,它们将应用于所有节点。
- 交换器联邦链路将在下游集群的任何节点上启动。如果它们运行的节点崩溃或停止,它们将故障转移到其他节点。
- 队列联邦链路将在与下游队列相同的节点上启动。如果下游队列是 仲裁队列,它们将在与主节点 (leader) 相同的节点上启动,并在未来的任何领导者选举后在新的主节点所在的节点上重新创建。
- 要连接到上游集群,您可以在单个上游中指定多个 URI。联邦链路进程每次尝试连接时都会随机选择其中一个 URI。
使用 TLS 保护联邦连接
从 Erlang 26 开始,TLS 实现默认启用TLS 客户端对等方验证。
如果未配置客户端 TLS 证书和密钥对,启用 TLS 的联邦链路将无法连接。必须为需要使用对等验证的启用 TLS 的联邦链路配置证书(公钥)和私钥对。
如果不需要对等验证,则可以将其禁用。
联邦连接(链路)可以使用 TLS 进行保护。由于联邦在底层使用 RabbitMQ 客户端,因此需要配置目标代理以 监听 TLS 连接,并配置联邦以使用 TLS。
要配置联邦以使用 TLS,需要
- 在上游 URI 中,使用
amqps作为方案而不是amqp,并使用端口5671而不是5672(假设使用默认端口,但端口是显式指定的) - 在同一个上游 URI 中,通过 URI 查询参数 指定 CA 证书和客户端证书/密钥对,以及其他参数(即 启用或禁用对等验证、对等验证深度)
- 可选地,通过 Erlang 客户端设置配置对所有链路通用的 TLS 相关 设置或默认值(加上可选的 Shovel)
在下面的示例中,上游 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 的策略将减少遇到此问题的风险。