参数和策略
概述
虽然 RabbitMQ 的大部分配置都位于 配置文件 中,但有些内容不适合使用配置文件。
- 如果它们需要在集群中的所有节点上保持一致
- 如果它们可能在运行时发生更改
RabbitMQ 将这些项目称为参数。可以通过调用 rabbitmqctl
或通过 HTTP API 设置参数。
参数有两种类型:虚拟主机作用域参数和全局参数。虚拟主机作用域参数与虚拟主机绑定,由组件名称、名称和值组成。
全局参数不与特定的虚拟主机绑定,它们由名称和值组成。
参数使用的一种特殊情况是 策略。
策略是指定队列和交换机 可选参数 以及 联合 和 传送 等插件的推荐方式。
策略是虚拟主机作用域的。
操作员策略 允许集群操作员覆盖常规策略中定义的某些参数。这种特殊的策略类型旨在定义防护栏,例如,限制最大队列大小,强制执行仲裁队列和流初始复制因子等。
在 RabbitMQ 作为服务提供的环境中,操作员策略尤其重要,即由一个团队操作但由多个其他团队或外部客户使用的环境。
全局和每个虚拟主机参数
如上所述,存在虚拟主机作用域参数和全局参数。虚拟主机作用域参数的一个示例是联合上游:它针对一个组件(federation-upstream
),它有一个用于标识它的名称,它与虚拟主机绑定(联合链接将针对此虚拟主机的一些资源),并且它的值定义了到上游代理的连接参数。
可以设置、清除和列出虚拟主机作用域参数
- 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 用于定义虚拟主机、交换机、队列、绑定、用户和权限的数据库中。参数与管理插件的导出功能一起导出其他对象定义。
虚拟主机作用域参数由联合和传送插件使用。全局参数由 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"}
导航到“管理”>“策略”>“添加/更新策略”。
在“名称”旁边输入策略名称(例如“federated”),在“模式”旁边输入模式(例如“^federated.”),并使用“应用于”下拉列表选择策略应应用于哪种类型的实体(本例中为交换机)。
在“策略”旁边的第一行输入“federation-upstream-set” =“all”(或特定上游名称)。
单击“添加策略”。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定地选择有效的策略。应避免此类情况,方法是注意各种策略使用的优先级。
这将为名称以 "federated."
开头的所有交换机,在虚拟主机 "/"
中,将值 "all"
与键 "federation-upstream-set"
匹配。
"pattern"
参数是用于匹配交换机或队列名称的正则表达式。
如果多个策略匹配同一个交换机或队列,则优先级最高的策略适用。
"apply-to"
参数可以是以下值之一:
"exchanges"
,仅应用于交换机"queues"
,应用于所有类型的队列,包括流"classic_queues"
,仅应用于经典队列"quorum_queues"
,仅应用于仲裁队列"streams"
,仅应用于流"all"
,应用于所有交换机和队列(包括流)
"apply-to"
和 "priority"
设置是可选的。默认值分别为 "all"
和 "0"
。
策略优先级
策略**模式**与交换机和队列**名称**匹配,以确定哪个策略(如果有)应该将一组键值对(该策略的定义)注入到匹配队列(交换机)的可选参数中。
最多只有一个策略匹配一个队列或交换机。由于多个策略可以匹配单个名称,因此需要一种机制来解决此类策略冲突。此机制称为策略优先级。每个策略都有一个与其关联的数字优先级。在声明策略时可以指定此优先级。如果未明确提供,则将使用优先级 0。
最多只有一个策略匹配一个队列或交换机。然后根据优先级对匹配的策略进行排序,优先级最高的策略将生效。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定地选择有效的策略。应避免此类情况,方法是注意各种策略使用的优先级。
然后根据优先级对匹配的策略进行排序,优先级最高的策略将生效。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定地选择有效的策略。应避免此类情况,方法是注意各种策略使用的优先级。
组合策略定义
在某些情况下,我们可能希望将多个策略定义应用于一个资源。例如,我们可能需要一个队列进行联合并且具有消息 TTL。在任何给定时间,最多只有一个策略将应用于一个资源,但我们可以在该策略中应用多个定义。
联合策略定义需要指定一个上游集,因此我们需要在我们的定义中包含 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"}
导航到“管理”>“策略”>“添加/更新策略”。
在“名称”旁边输入策略名称(例如“federated”),在“模式”旁边输入模式(例如“^federated.”),并使用“应用于”下拉菜单选择策略应应用于哪种实体(在本例中为队列)。
在“策略”旁边的第一行输入“federation-upstream-set” =“all”(或特定上游名称)。
单击“添加策略”。
通过这样做,所有与模式“^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
和用户策略都提供相同的键时,前者优先。
但是,如果也使用操作员策略,则该策略也将优先于客户端提供的参数。操作员策略是一种保护机制,会覆盖客户端提供的值和用户策略值。
使用操作员策略为与资源使用相关的应用程序控制参数引入防护栏(例如峰值磁盘空间使用量)。
定义操作员策略
操作员策略的定义方式与常规(用户)策略非常相似。当使用 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"}
导航到“管理”>“策略”>“添加/更新操作员策略”。
在“名称”旁边输入队列名称(在本例中为“transient-queue-ttl”),在“模式”旁边输入模式(在本例中为“^amq.”),并使用“应用于”下拉菜单选择策略应应用于哪种实体(在本例中为队列)。
在“策略”旁边的第一行输入“expires”= 1800000。
单击“添加策略”。
当多个策略匹配一个实体并且它们都具有相同的优先级时,将不确定地选择有效的策略。应避免此类情况,方法是注意各种策略使用的优先级。
如何禁用操作员策略更改
可以通过配置禁用通过 HTTP API 和 Web UI 修改操作员策略。这使得所有用户都无法通过 HTTP API 和 Web UI 对操作员策略进行读写。
management.restrictions.operator_policy_changes.disabled = true