[ English | Indonesia | русский ]

RabbitMQ 集群维护

RabbitMQ broker 是一个 Erlang 节点的一个或多个逻辑分组,每个节点运行 RabbitMQ 应用程序,并共享用户、虚拟主机、队列、交换器、绑定和运行时参数。节点集合通常被称为 集群。有关 RabbitMQ 集群的更多信息,请参阅 RabbitMQ 集群

在 OpenStack-Ansible 中,RabbitMQ 集群运行所需的所有数据和状态都复制到所有节点,包括消息队列,从而提供高可用性。RabbitMQ 节点使用域名相互寻址。集群所有成员的主机名必须可以从所有集群节点以及可能使用与 RabbitMQ 相关的 CLI 工具的任何机器解析。在更严格的环境中,也可以使用替代方案。有关该设置的更多详细信息,请参阅 Inet 配置

创建 RabbitMQ 集群

RabbitMQ 集群可以通过两种方式形成

  • 使用 rabbitmqctl 手动

  • 声明式(配置中的集群节点列表,使用 rabbitmq-autoclusterrabbitmq-clusterer 插件)

注意

RabbitMQ broker 可以容忍集群内单个节点的故障。只要它们能够在关闭时访问之前已知的成员,这些节点就可以随意启动和停止。

您可以配置两种类型的节点:磁盘节点和 RAM 节点。最常见的是,您会将节点用作磁盘节点(首选)。而 RAM 节点更多的是用于性能集群的特殊配置。

RabbitMQ 节点和 CLI 工具使用 erlang cookie 来确定它们是否具有通信权限。cookie 是一个字母数字字符串,可以短也可以长,由您决定。

注意

cookie 值是一个共享密钥,应受到保护并保密。

*nix 环境中,cookie 的默认位置是 /var/lib/rabbitmq/.erlang.cookie$HOME/.erlang.cookie

提示

在故障排除时,如果您发现一个节点拒绝加入集群,那么检查 erlang cookie 是否与其它节点匹配绝对值得。当 cookie 配置错误(例如,不相同)时,RabbitMQ 会记录诸如“来自禁止节点的连接尝试”和“无法自动集群”之类的错误。有关更多信息,请参阅 集群

要形成 RabbitMQ 集群,您首先获取独立的 RabbitMQ broker,然后将这些节点重新配置为集群配置。

使用 3 个节点的示例,您将告诉节点 2 和 3 加入第一个节点的集群。

  1. 登录到第 2 个和第 3 个节点并停止 RabbitMQ 应用程序。

  2. 加入集群,然后重新启动应用程序

    rabbit2$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit2 ...done.
    rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1
    Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
    rabbit2$ rabbitmqctl start_app
    Starting node rabbit@rabbit2 ...done.
    

检查 RabbitMQ 集群状态

  1. 从任何节点运行 rabbitmqctl cluster_status

您将看到 rabbit1rabbit2 都在像以前一样运行。

区别在于,输出的集群状态部分,现在两个节点都分组在一起了

rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
{running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.

要将第三个 RabbitMQ 节点添加到集群,请重复上述过程,停止第三个节点上的 RabbitMQ 应用程序。

  1. 加入集群,并在第三个节点上重新启动应用程序。

  2. 执行 rabbitmq cluster_status 以查看所有 3 个节点

    rabbit1$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
     {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]}]
    ...done.
    

停止并重新启动 RabbitMQ 集群

要停止和启动集群,请记住您关闭节点的顺序。您停止的最后一个节点,必须是您启动的第一个节点。该节点是 master

如果您以错误的顺序启动节点,您可能会遇到一个问题,即它认为当前的 master 不应该成为 master,并丢弃消息以确保在真正的 master 恢复之前,不会排队新的消息。

RabbitMQ 和 Mnesia

Mnesia 是一个分布式数据库,RabbitMQ 使用它来存储有关用户、交换器、队列和绑定的信息。但是,消息并未存储在数据库中。

有关 Mnesia 的更多信息,请参阅 Mnesia 概述

要查看重要 RabbitMQ 文件的位置,请参阅 文件位置

修复单个节点的已分区 RabbitMQ 集群

由于您的环境中的某些原因,您可能会失去集群中的一个节点。在这种情况下,多个 LXC 容器在同一主机上运行 RabbitMQ,并且位于单个 RabbitMQ 集群中。

如果主机仍然显示为集群的一部分,但未运行,请执行

# rabbitmqctl start_app

但是,您可能会注意到应用程序存在一些问题,因为客户端可能正在尝试将消息推送到未响应的节点。为了解决这个问题,请通过执行以下操作从集群中忘记该节点

  1. 确保 RabbitMQ 未在节点上运行

    # rabbitmqctl stop_app
    
  2. 在 RabbitMQ 第二个节点上,执行

    # rabbitmqctl forget_cluster_node rabbit@rabbit1
    

通过这样做,集群可以有效地继续运行,您可以修复故障节点。

重要提示

在您重新启动节点时要小心,它仍然会认为它是集群的一部分,并且需要您重置该节点。重置后,您应该能够将其重新加入到其它节点,如果需要的话。

rabbit1$ rabbitmqctl start_app
Starting node rabbit@rabbit1 ...

Error: inconsistent_cluster: Node rabbit@rabbit1 thinks it's clustered
       with node rabbit@rabbit2, but rabbit@rabbit2 disagrees

rabbit1$ rabbitmqctl reset
Resetting node rabbit@rabbit1 ...done.
rabbit1$ rabbitmqctl start_app
Starting node rabbit@mcnulty ...
...done.

修复多节点集群的已分区 RabbitMQ 集群

与存在于单个节点集群中的多节点集群相同的概念适用。唯一的区别是,各个节点实际上将运行在不同的主机上。在处理多节点集群时需要记住的关键事项是

  • 当整个集群被关闭时,最后一个关闭的节点必须是第一个启动的节点。如果这样不发生,节点将等待 30 秒,等待最后一个磁盘节点恢复在线,然后失败。

    如果最后一个关闭的节点无法启动,可以使用 forget_cluster_node 命令将其从集群中删除。

  • 如果所有集群节点以同时且不受控制的方式停止(例如,停电),您可能会遇到所有节点都认为其它节点在它们之后停止的情况。在这种情况下,您可以在一个节点上使用 force_boot 命令使其可再次启动。

有关更多信息,请参阅 rabbitmqctl 手册页。

迁移 HA 和 Quorum 队列

在 2024.1 (Caracal) 版本中,OpenStack-Ansible 默认切换到使用 RabbitMQ Quorum 队列,而不是遗留的高可用性经典队列。可以升级时执行迁移到 Quorum 队列,但可能会导致扩展的控制平面停机时间,因为这需要使用新的配置重新启动所有 OpenStack 服务。

为了加快迁移速度,可以运行以下 playbook 以迁移到或从 Quorum 队列,同时跳过软件包安装和其他配置任务。这些任务从 2024.1 版本开始可用。

$ openstack-ansible openstack.osa.rabbitmq_server --tags rabbitmq-config
$ openstack-ansible openstack.osa.setup_openstack --tags common-mq,post-install

为了利用这些步骤,我们建议在升级到 2024.1 之前将 oslomsg_rabbit_quorum_queues 设置为 false。然后,升级后,将 oslomsg_rabbit_quorum_queues 恢复为默认值 true 并运行上述 playbook。