跳至主要内容

RabbitMQ 3.7 中的新配置格式

·阅读时间:7 分钟

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

为什么要使用新的格式

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

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

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

但是,一旦项目积累了一定的用户基础,该格式也有一些明显的缺点

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

RabbitMQ 团队希望解决所有这些问题,尤其是最后一个问题。Chef 和 BOSH 等配置工具能够生成功能性配置文件,但这些代码难以阅读和维护,从而导致容易出错。

新格式

在评估了所有常见的候选项之后,我们选择了一种类似于 ini 的格式,该格式由 sysctl 和 Riak 使用。它使用不同的配置扩展名.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.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 查询。此类场景不太适合新格式,但必须支持它们。

为了解决这个问题,现在可以在经典(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 邮件列表上告诉我们您的想法!

© 2024 RabbitMQ. All rights reserved.