跳到主要内容

RabbitMQ 3.7 中的对等发现子系统

·9 分钟阅读

在这篇博文中,我们将更详细地了解 RabbitMQ 3.7.0 中引入的新子系统。

为什么我们需要对等发现?

开源数据服务(如 RabbitMQ)的用户对操作自动化有越来越高的期望。这包括所谓的 Day 1 操作:初始集群配置。

当首次形成 RabbitMQ 集群时,新启动的节点需要有一种方法来相互发现。在 3.6.x 及更早版本中,有两种方法可以做到这一点

  • CLI 工具
  • 配置文件中的节点列表

前一种选项被一些配置工具使用,但通常对自动化不太友好。后一种选项更方便,但有其自身的局限性:节点集是固定的,更改它需要重新部署配置文件和重启节点。

更好的方法

还有第三种选择,它已经在社区中存在了几年:rabbitmq-autocluster,一个最初由 Gavin Roy 开发的插件。该插件修改了 RabbitMQ 启动过程并注入了一个对等发现步骤。在这种情况下,对等节点列表不必来自配置文件:它可以从 AWS 自动伸缩组或外部工具(如 etcd)中检索。

rabbitmq-autocluster 的作者得出结论,没有一种真正的执行对等发现的方法,不同的方法对于不同的部署场景更有意义。因此,他们引入了一个可插拔的接口。这个可插拔接口的特定实现称为对等发现机制。鉴于过去几年平台和部署自动化堆栈的爆炸式增长,这被证明是一个明智的决定。

对于 RabbitMQ 3.7.0,我们采用了 rabbitmq-autocluster,并将其主要思想集成到核心中,并根据我们支持生产 RabbitMQ 安装和社区反馈的经验进行了一些修改。

结果是一个新的对等发现子系统

它是如何工作的?

当节点启动并检测到它没有先前初始化的数据库时,它将检查是否配置了对等发现机制。如果是这种情况,它将执行发现并按顺序尝试联系每个发现的对等节点。最后,它将尝试加入第一个可达对等节点的集群。

某些机制假定所有集群成员都是预先知道的(例如,在配置文件中列出),而另一些机制是动态的(节点可以来来去去)。

RabbitMQ 3.7 附带了许多机制

  • AWS (EC2 实例标签或自动伸缩组)
  • Kubernetes
  • etcd
  • Consul
  • 预配置的 DNS 记录
  • 配置文件

并且将来很容易引入对更多选项的支持。

由于在配置文件中列出集群节点的功能并不新鲜,让我们关注新功能。

节点注册和注销

某些机制使用数据存储来跟踪节点列表。新加入的集群成员更新数据存储以指示其存在。etcdConsul 是通过 RabbitMQ 附带的插件支持的两个选项。

对于其他机制,集群成员资格是带外管理的(通过 RabbitMQ 节点无法控制的机制)。例如,AWS 机制使用 EC2 实例过滤或自动伸缩组会员资格,这两者都由 AWS 管理和更新。

使用预配置的集合

理论讲够了,让我们来看看使用在 3.7 中与对等发现一起引入的新配置格式来配置对等发现的节点列表需要做什么

首先,我们必须告诉 RabbitMQ 使用经典的配置机制进行对等发现。这通过使用 cluster_formation.peer_discovery_backend 键来完成。然后使用 cluster_formation.classic_config.nodes 列出一个或多个节点,这是一个集合

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config

cluster_formation.classic_config.nodes.1 = rabbit@hostname1.eng.example.local
cluster_formation.classic_config.nodes.2 = rabbit@hostname2.eng.example.local

就是这样。

这种发现方法可能是最容易入门的,但它有一个明显的缺点:节点列表是静态的。

接下来,让我们看看一种使用动态节点列表的机制:AWS EC2 实例过滤。

使用 AWS 实例过滤

就像前面的示例一样,我们必须告诉节点使用 AWS 进行对等发现

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_aws

有两种使用 AWS 机制的方法,但后端名称(模块)对于两者是相同的。

要使用实例过滤,插件需要配置 AWS 区域以及一对凭据。敏感的配置文件值可以加密

这是一个同时执行这两项操作的配置文件示例

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_aws

cluster_formation.aws.region = us-east-1
cluster_formation.aws.access_key_id = ANIDEXAMPLE
cluster_formation.aws.secret_key = WjalrxuTnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY

节点现在有足够的信息来尝试咨询 EC2 实例元数据服务

最后,操作员需要提供一组要过滤的标签。标签是键/值对。这意味着可以基于多个标签进行过滤,例如,rabbitmq 和集群名称或环境类型(例如,developmenttestproduction)。

这是一个完整的配置示例,它使用 3 个标签:regionserviceenvironment

cluster_formation.peer_discovery_backend = rabbit_peer_discovery_aws

cluster_formation.aws.region = us-east-1
cluster_formation.aws.access_key_id = ANIDEXAMPLE
cluster_formation.aws.secret_key = WjalrxuTnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY

cluster_formation.aws.instance_tags.region = us-east-1
cluster_formation.aws.instance_tags.service = rabbitmq
cluster_formation.aws.instance_tags.environment = staging

我们已经完成了这个示例的设置。唯一剩下的要讨论的是如何处理在首次形成集群时发生的自然竞争条件,此时节点列表只能返回一个空集。这将在下面的单独部分中介绍。

IAM 角色和权限

如果将 IAM 角色分配给运行 RabbitMQ 节点的 EC2 实例,则必须使用策略来允许所述实例使用 EC2 实例元数据服务。这是一个此类策略的示例

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingInstances",
"ec2:DescribeInstances"
],
"Resource": [
"*"
]
}
]
}

如果没有此策略,AWS 对等发现插件将无法列出实例,并且发现将失败。当发现失败时,节点将认为这是一个致命条件并终止。

节点名称

默认情况下,使用 AWS 对等发现的节点名称将使用私有主机名计算。也可以切换到私有 IP 地址

cluster_formation.aws.use_private_ip = true

对等发现的先有鸡还是先有蛋的问题

考虑一种部署,其中整个集群一次性配置,并且所有节点并行启动。例如,它们可能是刚由 BOSH 或 AWS Cluster Formation 模板创建的。在这种情况下,节点注册之间存在自然的竞争条件,并且多个节点可能成为“第一个注册”(发现没有现有对等节点,因此作为独立节点启动)。

不同的对等发现后端使用不同的方法来最大限度地减少这种情况的可能性。一些后端使用其数据服务(etcd、Consul)获取锁,并在注册后释放它,如果锁获取失败,则重试。

其他后端使用一种称为随机启动延迟的技术。使用随机启动延迟,节点将延迟其启动一段随机选取的值(默认情况下在 5 到 60 秒之间)。虽然这种策略起初可能看起来很幼稚,但实际上在最大延迟间隔足够高的情况下效果很好。它也用于某些分布式系统算法中的领导者选举,例如 Raft

某些后端(配置文件、DNS)依赖于预配置的对等节点集,并且不会遇到此问题,因为当节点尝试加入其对等节点时,它将继续重试一段时间。

对等发现不做的事情

引入对等发现是为了解决一组狭窄的问题。它不会改变 RabbitMQ 集群一旦形成后的运行方式。即使某些机制引入了其他功能,某些问题(共享密钥分发监控,例如)也应该由不同的工具解决。

对等发现也由空白(未初始化)节点执行。如果节点之前是集群成员,它将在启动时尝试联系其“最后看到的”对等节点一段时间。在这种情况下,将不执行对等发现。这与早期 RabbitMQ 版本在这种场景下的工作方式没有什么不同。

对等发现故障排除

推理一个自动化集群形成系统,该系统也使用具有外部依赖项(例如 AWS API 或 etcd)的对等发现机制,这可能很棘手。因此,所有对等发现实现都会记录关键决策,并且大多数会在 debug 日志级别记录所有外部请求。如有疑问,请启用 debug 日志记录并查看节点日志!

并记住上面关于对等发现不应启动的情况部分中涵盖的内容。

rabbitmq-autocluster 的区别

虽然新的对等发现子系统在许多方面与 rabbitmq-autocluster 相似,但对于操作员来说,存在一些重要的区别。

使用 rabbitmq-autocluster,节点将在加入其对等节点之前重置自身。这在某些环境中是有意义的,而在另一些环境中则没有意义。RabbitMQ 核心中的对等发现不会这样做。

除了 RabbitMQ 配置文件之外,rabbitmq-autocluster 还允许使用环境变量进行特定于机制的配置。虽然保留此功能是为了简化迁移,但应将其视为 3.7.0 中对等发现子系统已弃用的功能。

核心中的对等发现大量使用了新的配置文件格式rabbitmq-autocluster 不支持该格式,因为它现在实际上是一个仅限 3.6.x 的插件。

未来工作

本文中描述的对等发现子系统的大多数主要方面都通过 rabbitmq-autocluster 进行了几年的实战测试。然而,随着越来越多的用户在越来越多的环境中使用此功能,来自更广泛的用户和用例的新反馈不断积累。

目前,一个尚未解决的问题是,是否应立即将无法联系对等发现机制使用的外部服务(例如 AWS API 端点或 etcd 或 DNS)视为导致节点停止的致命故障,或者是否应在一段时间内重试对等发现。欢迎您在 RabbitMQ 邮件列表上提供反馈。

© . All rights reserved.