参数和策略
概述
虽然 RabbitMQ 的大部分配置都位于配置文件中,但有些内容与配置文件的使用不太协调
- 如果它们需要在集群中的所有节点上保持一致
- 如果它们可能在运行时更改
RabbitMQ 将这些项称为参数。可以通过调用rabbitmqctl
或通过HTTP API设置参数。
参数有两种:虚拟主机作用域参数和全局参数。虚拟主机作用域参数与虚拟主机绑定,由组件名称、名称和值组成。
全局参数不与特定的虚拟主机绑定,它们由名称和值组成。
策略是参数使用的一个特殊情况,请参阅策略。
策略是指定队列和交换机组的可选参数以及诸如 Federation 和 Shovel 等插件的推荐方式。
策略是虚拟主机作用域的。
操作员策略允许集群操作员覆盖在常规策略中定义的某些参数。这种特殊的策略类型旨在定义护栏,例如,限制最大队列大小,强制仲裁队列和流初始复制因子等等。
操作员策略在 RabbitMQ 作为服务提供的环境中尤为重要,也就是说,RabbitMQ 由一个团队运营,但由多个其他团队或外部客户使用。
全局和每个虚拟主机的参数
如上所述,参数分为虚拟主机作用域参数和全局参数。虚拟主机作用域参数的一个例子是 Federation 上游:它针对一个组件 (federation-upstream
),它有一个标识它的名称,它与一个虚拟主机绑定(Federation 链接将针对此虚拟主机的某些资源),并且其值定义了到上游 Broker 的连接参数。
可以设置、清除和列出虚拟主机作用域参数
- bash
- PowerShell
- HTTP API
# sets a runtime parameter in a virtual host
rabbitmqctl set_parameter [-p vhost] <component_name> <name> <value>
# clears (unsets) a runtime parameter in a virtual host
rabbitmqctl clear_parameter [-p vhost] <component_name> <name>
# lists runtime parameters in a virtual host
rabbitmqctl list_parameters [-p vhost]
# sets a runtime parameter in a virtual host
rabbitmqctl.bat set_parameter [-p vhost] <component_name> <name> <value>
# clears (unsets) a runtime parameter in a virtual host
rabbitmqctl.bat clear_parameter [-p vhost] <component_name> <name>
# lists runtime parameters in a virtual host
rabbitmqctl.bat list_parameters [-p vhost]
PUT /api/parameters/{component_name}/{vhost}/{name}
DELETE /api/parameters/{component_name}/{vhost}/{name}
GET /api/parameters
全局参数是另一种参数。全局参数的一个例子是集群的名称。可以设置、清除和列出全局参数
- bash
- PowerShell
- HTTP API
# sets a global (virtual-host-independent) runtime parameter
rabbitmqctl set_global_parameter <name> <value>
# clears (unsets) a global (virtual-host-independent) runtime parameter
rabbitmqctl clear_global_parameter <name>
# lists global (virtual-host-independent) runtime parameters
rabbitmqctl list_global_parameters
# sets a global (virtual-host-independent) runtime parameter
rabbitmqctl.bat set_global_parameter <name> <value>
# clears (unsets) a global (virtual-host-independent) runtime parameter
rabbitmqctl.bat clear_global_parameter <name>
# lists global (virtual-host-independent) runtime parameters
rabbitmqctl.bat list_global_parameters
PUT /api/global-parameters/name
DELETE /api/global-parameters/name
GET /api/global-parameters
由于参数值是 JSON 文档,因此在使用 rabbitmqctl
在命令行上创建参数时,通常需要引用它。在 Unix 上,通常最简单的方法是用单引号引用整个文档,并在其中使用双引号。在 Windows 上,您必须转义每个双引号。因此,我们给出了 Unix 和 Windows 的示例。
参数驻留在 RabbitMQ 用于虚拟主机、交换机、队列、绑定、用户和权限定义的数据库中。参数与管理插件的导出功能导出的其他对象定义一起导出。
Federation 和 Shovel 插件使用虚拟主机作用域参数。MQTT 插件使用全局参数。
策略
策略是一种配置队列、流、交换机组的某些属性的机制。它们专为运行时可以更改的参数而设计。
由于队列(流)类型在声明时设置,并且无法更改,因此策略不能用于配置队列类型,这是设计使然。要指定队列(流)类型,请使用可选参数。
策略是配置队列、交换机和某些插件的可选参数的推荐方式。
两个值得注意的例外是队列类型和经典队列的最大优先级数。这些值有意不能通过策略配置:它们的值在队列声明时固定。
为什么存在策略
在我们解释策略是什么以及如何使用它们之前,解释一下为什么将它们引入 RabbitMQ 会有所帮助。
除了强制属性(例如 durable
或 exclusive
)之外,RabbitMQ 中的队列和交换机还具有可选参数,有时也称为 x-arguments
。
这些参数由客户端在声明队列(交换机)时提供,并控制各种可选功能,例如队列长度限制或TTL。
RabbitMQ 支持的某些协议中客户端控制的属性通常运行良好,但它们可能不够灵活:以这种方式更新 TTL 值或镜像参数需要应用程序更改、重新部署和队列重新声明(这涉及删除)。此外,没有办法控制队列和交换机组的额外参数。引入策略是为了解决上述痛点。
策略通过名称(使用正则表达式模式)匹配一个或多个队列,并将其定义(可选参数的映射)附加到匹配队列的 x-arguments。换句话说,可以使用策略一次配置多个队列的 x-arguments,并通过更新策略定义一次更新它们。
在现代版本的 RabbitMQ 中,可以通过策略控制的功能集与可以通过客户端提供的参数控制的功能集不相同。
策略如何工作
关键策略属性是
- 名称:它可以是任何内容,但建议使用不带空格的基于 ASCII 的名称
- 模式:一个正则表达式,用于匹配一个或多个队列(交换机)名称。可以使用任何正则表达式。
- 定义:一组键/值对(可以看作是 JSON 文档),将被注入到匹配队列和交换机的可选参数映射中
- 策略优先级用于确定当多个策略与其名称匹配时,应将哪个策略应用于队列或交换机
策略自动与交换机和队列匹配,并帮助确定它们的行为方式。每个交换机或队列最多有一个策略匹配(请参阅下面的组合策略定义),然后每个策略将一组键值对(策略定义)注入到匹配的队列(交换机)上。
策略只能匹配特定类型的队列、所有队列、仅交换机或所有队列和交换机。这在使用 apply-to
标志创建策略时控制。
策略可以随时更改。当策略定义更新时,它对匹配的交换机和队列的影响将重新应用。通常情况下,这会立即发生,但对于非常繁忙的队列,可能需要一点时间(例如,几秒钟)。
每次创建交换机或队列时,都会匹配和应用策略,而不仅仅是在创建策略时。
策略可用于配置
以及其他功能。
定义策略的示例如下所示
- bash
- PowerShell
- HTTP API
- 管理 UI
rabbitmqctl set_policy federate-me \
"^federated\." '{"federation-upstream-set":"all"}' \
--priority 1 \
--apply-to exchanges
rabbitmqctl.bat set_policy federate-me ^
"^federated\." "{""federation-upstream-set"":""all""}" ^
--priority 1 ^
--apply-to exchanges
PUT /api/policies/%2f/federate-me
{"pattern": "^federated\.",
"definition": {"federation-upstream-set":"all"},
"priority": 1,
"apply-to": "exchanges"}
导航到
Admin
>Policies
>Add / update a policy
。在“名称”旁边输入策略名称(例如“federated”),在“模式”旁边输入模式(例如“^federated.”),并使用
Apply to
下拉列表选择策略应应用于哪种类型的实体(本例中为交换机)。在“策略”旁边的第一行输入“federation-upstream-set” = “all”(或特定的上游名称)。
单击
Add policy
。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定性地选择有效的策略。应避免这种情况,注意各种策略使用的优先级。
这会将值 "all"
与键 "federation-upstream-set"
匹配,用于虚拟主机 "/"
中名称以 "federated."
开头的所有交换机。
"pattern"
参数是一个正则表达式,用于匹配交换机或队列名称。
如果多个策略可以匹配给定的交换机或队列,则应用优先级最高的策略。
"apply-to"
参数可以是以下之一
"exchanges"
,仅应用于交换机"queues"
,应用于所有类型的队列,包括流"classic_queues"
,仅应用于经典队列"quorum_queues"
,仅应用于仲裁队列"streams"
,仅应用于流"all"
,应用于所有交换机和队列(包括流)
"apply-to"
和 "priority"
设置是可选的。默认值分别为 "all"
和 "0"
。
策略优先级
策略模式与交换机和队列名称匹配,以确定哪个策略(如果有)应将一组键值对(该策略的定义)注入到匹配队列(交换机)的可选参数中。
最多一个策略匹配一个队列或交换机。由于多个策略可以匹配单个名称,因此需要一种机制来解决此类策略冲突。这种机制称为策略优先级。每个策略都有一个与之关联的数字优先级。可以在声明策略时指定此优先级。如果未显式提供,则将使用优先级 0(非常低的优先级)。
最多一个策略匹配一个队列或交换机。然后,匹配的策略按优先级排序,优先级最高的策略将生效。
值越高表示优先级越高:优先级为 10 的策略将覆盖优先级为 8 的策略,并且两者都将覆盖默认优先级 0。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定性地选择有效的策略。应避免这种情况,注意各种策略使用的优先级。
然后,匹配的策略按优先级排序,优先级最高的策略将生效。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定性地选择有效的策略。应避免这种情况,注意各种策略使用的优先级。
组合策略定义
在某些情况下,我们可能希望将多个策略定义应用于资源。例如,我们可能需要一个 Federated 队列并具有消息 TTL。任何给定时间最多只有一个策略将应用于资源,但我们可以在该策略中应用多个定义。
Federation 策略定义将需要指定一个上游集,因此我们需要在我们的定义中使用 federation-upstream-set
键。另一方面,要将某些队列定义为启用 TTL 的队列,我们需要为策略定义 TTL 相关的键。策略定义只是一个 JSON 对象,可以在同一策略定义中组合多个键。
这是一个例子
- bash
- PowerShell
- HTTP API
- 管理 UI
rabbitmqctl set_policy ttl-fed \
"^tf\." '{"federation-upstream-set":"all", "message-ttl":60000}' \
--priority 1 \
--apply-to queues
rabbitmqctl set_policy ttl-fed ^
"^tf\." "{""federation-upstream-set"":""all"", ""message-ttl"":60000}" ^
--priority 1 ^
--apply-to queues
PUT /api/policies/%2f/ttl-fed
{"pattern": "^tf\.",
"definition": {"federation-upstream-set":"all", "message-ttl":60000},
"priority": 1,
"apply-to": "queues"}
导航到
Admin
>Policies
>Add / update a policy
。在“名称”旁边输入策略名称(例如“federated”),在“模式”旁边输入模式(例如“^federated.”),并使用
Apply to
下拉列表选择策略应应用于哪种类型的实体(本例中为队列)。在“策略”旁边的第一行输入“federation-upstream-set” = “all”(或特定的上游名称)。
单击
Add policy
。
通过这样做,所有与模式“^tf\.”匹配的队列都将应用 "federation-upstream-set"
和策略定义。
操作员策略
与常规策略的区别
有时,操作员有必要强制执行某些策略。例如,可能需要强制队列 TTL,但仍然允许其他用户管理策略。操作员策略允许这样做。
操作员策略与常规策略非常相似,但它们的定义使用方式不同。在将结果应用于匹配的队列之前,它们会与常规策略定义合并。
由于操作员策略可能会意外更改队列属性,进而更改应用程序的假设和语义,因此它们仅限于少数几个参数
经典 | 仲裁 | 流 | |
delivery-limit | ✓ | ||
---|---|---|---|
expires | ✓ | ✓ | |
max-in-memory-bytes | ✓ | ||
max-in-memory-length | ✓ | ||
max-length | ✓ | ✓ | |
max-length-bytes | ✓ | ✓ | ✓ |
message-ttl | ✓ | ✓ | |
target-group-size | ✓ |
与常规策略的冲突解决
操作员策略和常规策略可以在其定义中包含相同的键。当发生这种情况时,将选择更保守的值作为有效值。例如,如果匹配的操作员策略定义将 max-length
设置为 50,而匹配的常规策略定义使用值 100,则将使用值 50。但是,如果常规策略的值为 20,则将使用该值。因此,操作员策略不仅仅覆盖常规策略值。它们强制执行限制,但尽量不覆盖用户提供的策略(如果可能)。
经典 | 仲裁 | 流 | |
delivery-limit |
| ||
---|---|---|---|
expires |
|
| |
max-in-memory-bytes |
| ||
max-in-memory-length |
| ||
max-length |
|
| |
max-length-bytes |
|
|
|
message-ttl |
|
| |
target-group-size |
|
当 客户端提供的 x-arguments
和用户策略都提供相同的键时,前者优先。此规则的例外是所有流配置设置以及仲裁队列的 (x-)overflow
,其中策略优先。
但是,如果也使用了操作员策略,则操作员策略也将优先于客户端提供的参数。操作员策略是一种保护机制,会覆盖客户端提供的值和用户策略值。
使用操作员策略为与资源使用相关的应用程序控制的参数引入护栏(例如,峰值磁盘空间使用量)。
定义操作员策略
操作员策略的定义方式与常规(用户)策略非常相似。当使用 rabbitmqctl
时,命令名称为 set_operator_policy
而不是 set_policy
。在 HTTP API 中,请求路径中的 /api/policies/
变为 /api/operator-policies/
- bash
- PowerShell
- HTTP API
- 管理 UI
rabbitmqctl set_operator_policy transient-queue-ttl \
"^amq\." '{"expires":1800000}' \
--priority 1 \
--apply-to queues
rabbitmqctl.bat set_operator_policy transient-queue-ttl ^
"^amq\." "{""expires"": 1800000}" ^
--priority 1 ^
--apply-to queues
PUT /api/operator-policies/%2f/transient-queue-ttl
{"pattern": "^amq\.",
"definition": {"expires": 1800000},
"priority": 1,
"apply-to": "queues"}
导航到
Admin
>Policies
>Add / update an operator policy
。在“名称”旁边输入队列名称(本例中为“transient-queue-ttl”),在
Pattern
旁边输入模式(本例中为“^amq.”),并使用Apply to
下拉列表选择策略应应用于哪种类型的实体(本例中为队列)。在“策略”旁边的第一行输入“expires” = 1800000。
单击
Add policy
。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定性地选择有效的策略。应避免这种情况,注意各种策略使用的优先级。
如何禁用操作员策略更改
可以通过配置禁用通过 HTTP API 和 Web UI 修改操作员策略。这使得操作员策略通过 HTTP API 和 Web UI 对所有用户都是只读的。
management.restrictions.operator_policy_changes.disabled = true