跳至主内容

RabbitMQ 3.7 中的新配置格式

·阅读 7 分钟

在本篇博文中,我们将介绍 RabbitMQ 3.7.0 中提供的一种新配置格式。

为什么我们需要一种新格式

许多开发人员和运维人员对软件配置格式都有自己的看法。关于特定格式的优缺点的争论通常围绕可读性、格式是否支持注释等展开。

这些确实是合理的顾虑,但配置文件并非总是由人工编写。在自动化期望日益增长的时代,特定格式的生成便利性却很少被讨论。

从历史上看,RabbitMQ 使用 Erlang 术语文件进行配置。除了是配置基于 Erlang 的系统的标准方法外,它在功能和安全性之间取得了良好的平衡:可以使用任何 Erlang 数据结构,包括任意嵌套,但不能评估任意代码。

然而,这种格式也有一些缺点,随着项目用户数量的增长,这些缺点变得越来越明显。

  • 对于刚开始使用 RabbitMQ 的人来说,这种格式并不熟悉
  • 它有一些微妙之处,比如需要尾随的点和逗号,这会让初学者感到困惑。
  • 任意嵌套虽然强大且有时是必要的,但也会极大地复杂化配置文件生成。
  • 在某些情况下,为了不必要的理由,需要熟悉不同的 Erlang 数据类型(例如,列表与二进制)。

Team RabbitMQ 希望解决所有这些问题,特别是最后一个。像 Chef 和 BOSH 这样的配置工具设法生成功能性的配置文件,但代码难以阅读和维护,从而导致容易出错。

新格式

在评估了所有常规选项后,我们选择了 sysctl 和 Riak 使用的一种类似 ini 的格式。它使用不同的配置文件扩展名 .conf,看起来像这样:

heartbeat = 30

这将覆盖服务器提供的默认心跳值为 30 秒。

大多数设置使用单行,配置键和值之间用等号和零个或多个空格分隔。这种格式已经存在了几十年,以其对人类来说相当易读而闻名。

这是一个稍微长一点的例子:

heartbeat = 30

listeners.tcp.default = 5672

除了心跳设置外,它还配置了一个 TCP 监听器,使用端口 5672 并绑定到所有可用的接口。

设置可以使用点进行结构化(逻辑分组)。例如,所有纯 TCP(与 TCP 加 TLS 相反)监听器设置都分组在 listener.tcp.* 下。

以下是在新格式中配置 TLS 证书和密钥的方式:

ssl_options.cacertfile           = /path/to/testca/cacert.pem
ssl_options.certfile = /path/to/server/cert.pem
ssl_options.keyfile = /path/to/server/key.pem
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true

与经典(Erlang 术语)格式中的相同设置进行比较:

[
{rabbit, [{ssl_options, [{cacertfile, "/path/to/testca/cacert.pem"},
{certfile, "/path/to/server/cert.pem"},
{keyfile, "/path/to/server/key.pem"},
{verify, verify_peer},
{fail_if_no_peer_cert, true}]}]}
].

除了更易读之外,新版本也更容易生成。

它还有一个不那么明显的改进:值现在使用模式进行验证。对于像私钥路径这样的路径值,这意味着如果找不到文件或无法读取,节点将立即报告并拒绝启动。以前,节点会启动,但文件会在运行时加载失败,这很容易让部署和监控工具感到困惑。

需要数值的字段将拒绝接受字符串,依此类推。新格式提供了一些静态类型的好处,这与许多常用格式不同。

集合

在此格式中,单值键的配置非常简单。但集合呢?例如,可以配置多个 TCP 监听器。也可以列出集群节点以进行对等发现。此格式如何处理这些问题?

新格式支持字典(maps)集合。对于数组或集合类型的值,会忽略键。以下是如何为对等发现指定节点列表:

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config

cluster_formation.classic_config.nodes.1 = rabbit1@hostname
cluster_formation.classic_config.nodes.2 = rabbit2@hostname
cluster_formation.classic_config.nodes.3 = rabbit3@hostname
cluster_formation.classic_config.nodes.4 = rabbit4@hostname

此示例中的键是 12 等。可以使用任何键值。顺序增长的数字易于生成,因此我们的文档示例使用了它们。

注释

新格式支持注释,使我们能够继续提供带注释的示例文件

## Select an authentication/authorisation backend to use.
##
## Alternative backends are provided by plugins, such as rabbitmq-auth-backend-ldap.
##
## NB: These settings require certain plugins to be enabled.
##
## Related doc guides:
##
## * https://rabbitmq.cn/plugins.html
## * https://rabbitmq.cn/access-control.html
##

auth_backends.1 = rabbit_auth_backend_internal

## uses separate backends for authentication and authorisation,
## see below.
# auth_backends.1.authn = rabbit_auth_backend_ldap
# auth_backends.1.authz = rabbit_auth_backend_internal

高级配置

尽管此格式很好,但它也有一些限制。考虑以下配置文件,它演示了LDAP 插件中的一些功能:

[
{rabbit, [{auth_backends, [rabbit_auth_backend_ldap]}]},
{rabbitmq_auth_backend_ldap,
[ {servers, ["my-ldap-server"]},
{user_dn_pattern, "cn=${username},ou=People,dc=example,dc=com"},
{use_ssl, false},
{port, 389},
{log, false},
{vhost_access_query, {in_group,
"ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}},
{resource_access_query,
{for, [{permission, configure, {in_group, "cn=admin,dc=example,dc=com"}},
{permission, write,
{for, [{resource, queue, {in_group, "cn=admin,dc=example,dc=com"}},
{resource, exchange, {constant, true}}]}},
{permission, read,
{for, [{resource, exchange, {in_group, "cn=admin,dc=example,dc=com"}},
{resource, queue, {constant, true}}]}}
]
}},
{topic_access_query,
{for, [{permission, write, {match, {string, "${routing_key}"}, {string, "^a"}}},
{permission, read, {constant, true}}
]
}},
{tag_queries, [{administrator, {constant, false}},
{management, {constant, true}}]}
]
}
].

此示例使用深度嵌套的数据结构来表达 LDAP 查询。这种情况不太适合新格式,但必须支持。

为了解决这个问题,现在可以指定另一个配置文件 advanced.config,它使用经典(Erlang 术语)配置格式

然后合并这两个配置文件。这如何实现?诀窍在于将新格式转换为旧格式,我们将在下面介绍。

或者,也可以仅使用旧的配置格式。例如,这在过渡期间是合理的。

工作原理

如上所述,新格式在底层被转换为经典格式,因为许多库(包括 Erlang/OTP 中的库)都期望这种格式。转换由一个名为 Cuttlefish 的工具完成,该工具最初由 Basho Technologies 开发。启动时,RabbitMQ 节点使用 Cuttlefish 执行以下操作:

  • 收集所有插件的配置模式文件
  • 运行 Cuttlefish 进行转换
  • 将结果与 advanced.config 文件合并
  • 加载最终配置

对于 RabbitMQ 核心和插件,这个过程是完全透明的。所有繁重的工作都由一组函数完成,这些函数构成了转换模式。Cuttlefish 进行解析并调用模式函数来执行验证和转换。

插件配置

具有可配置设置的插件现在会附带自己的模式,这些模式在节点启动时被提取并合并到主模式中。

以下是管理插件配置可能的样子:

management.listener.port = 15672
management.listener.ip = 127.0.0.1
management.listener.ssl = true

management.listener.ssl_opts.cacertfile = /path/to/cacert.pem
management.listener.ssl_opts.certfile = /path/to/cert.pem
management.listener.ssl_opts.keyfile = /path/to/key.pem

management.* 键的模式文件由管理插件提供。

结论

这种新格式使 RabbitMQ 配置文件对人类更加熟悉和易读,更容易被工具生成,并引入了针对可扩展模式的值验证。插件可以提供自己的配置模式文件并受益于新格式。

仍然可以使用以前的格式或组合这两种格式。但我们相信新格式可以覆盖绝大多数(80%)用例。

请查看更新的配置指南,尝试此功能,并在RabbitMQ 邮件列表上告诉我们您的想法!

© . This site is unofficial and not affiliated with VMware.