跳到主要内容

RabbitMQ 3.7 中的新配置格式

·7 分钟阅读

在这篇文章中,我们将介绍 RabbitMQ 3.7.0 中提供的新配置格式。

为什么我们需要新格式

许多开发人员和运维人员对软件配置格式有强烈的看法。关于特定格式的优缺点的争论集中在可读性、格式是否支持注释等等。

这些确实是合理的担忧,但配置文件并非总是由人手工制作。在自动化期望日益提高的时代,很少有人讨论特定格式的生成难易程度。

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

然而,一旦项目积累了相当数量的用户,这种格式也暴露出了一些缺点

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

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 监听器。也可以列出集群节点以用于对等发现目的。这种格式如何解决这个问题?

新格式支持作为映射(字典)的集合。对于作为数组或集合的值,将忽略键。以下是如何为对等发现指定节点列表的方法

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.org.cn/plugins.html
## * https://rabbitmq.org.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 查询。这种情况不太适合新格式,但必须支持它们。

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

然后合并这两种配置格式。这是如何实现的?诀窍是将新格式转换为旧格式,我们将在接下来介绍。

或者,也可以仅使用旧版配置格式。例如,在过渡期间,这样做是有意义的。

它是如何工作的

如上所述,新格式在底层被转换为经典格式,因为这是包括 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 邮件列表上告诉我们您的想法!

© . All rights reserved.