部署RabbitMQ主备集群的分步指南

构建RabbitMQ主备架构,涵盖集群配置、Erlang Cookie匹配、仲裁队列及经过验证的故障转移路径。

部署RabbitMQ主备集群的分步指南

RabbitMQ的高可用性不仅仅需要两台能够互相通信的服务器。你需要集群来实现共享元数据、复制队列来保证消息可用性,以及为客户端提供清晰的故障转移路径。

本指南展示了RabbitMQ在主备风格部署中的配置。客户端的故障转移通常由负载均衡器、DNS变更、服务发现或RabbitMQ外部的虚拟IP管理。

主备集群的先决条件

在开始配置之前,请确保所有目标集群节点(节点A-主节点,节点B-备节点)满足以下先决条件:

  1. 兼容的软件版本: 保持各节点上的RabbitMQ Server和Erlang/OTP版本一致。实践中,除非遵循RabbitMQ官方文档的滚动升级路径,否则应在每个节点上运行相同的RabbitMQ版本。
  2. 网络可达性: 节点必须能够通过客户端使用的AMQP端口、用于集群的分布端口以及你启用的任何管理或TLS端口进行通信。
  3. 主机名解析: 在所有节点上配置/etc/hosts文件(或DNS),使每个节点能够可靠地解析其他所有节点的主机名。
  4. Cookie一致性: 所有节点上的Erlang“魔法cookie”必须完全相同。这对于节点之间相互信任以进行集群至关重要。

确保Cookie一致性

Erlang cookie决定了节点之间能否安全通信。必须将其从第一个初始化的节点复制到所有其他节点。

在节点A(第一个节点)上:

找到cookie文件(通常位于/var/lib/rabbitmq/.erlang.cookie~/.erlang.cookie,具体取决于安装方式)并复制其内容。

在节点B(及后续节点)上:

  1. 停止RabbitMQ服务:
    sudo systemctl stop rabbitmq-server
    
  2. 用从节点A复制的内容替换现有的cookie文件,并确保正确的权限(通常为400)。
    # 使用echo的示例(根据需要替换内容)
    echo "YOUR_LONG_COOKIE_STRING" | sudo tee /var/lib/rabbitmq/.erlang.cookie
    sudo chmod 400 /var/lib/rabbitmq/.erlang.cookie
    
  3. 在节点B上启动服务:
    sudo systemctl start rabbitmq-server
    

步骤1:配置主机名和网络

确保节点A和节点B上的主机文件正确映射了它们的主机名。

示例/etc/hosts(在两台服务器上):

192.168.1.10   rabbitmq-node-a
192.168.1.11   rabbitmq-node-b

步骤2:初始化第一个集群节点(主节点)

节点A将是初始主节点,集群首先在此建立。

  1. 在节点A上启动服务(如果尚未运行):
    sudo systemctl start rabbitmq-server
    
  2. 验证状态: 确保节点正常运行。
    rabbitmqctl status
    

步骤3:将第二个节点(备节点)加入集群

现在,我们指示节点B加入由节点A领导的集群。

  1. 停止节点B上的RabbitMQ应用程序,同时保持Erlang节点可用:

    sudo rabbitmqctl stop_app
    
  2. 重置节点B的本地状态(如果它已被初始化为独立节点):

    sudo rabbitmqctl reset
    
  3. 加入命令: 在节点B上执行加入命令,指定节点A的主机名作为对等节点。

    sudo rabbitmqctl join_cluster rabbit@rabbitmq-node-a
    

    提示:使用在/etc/hosts中定义的主机名。

  4. 在节点B上启动RabbitMQ应用程序:

    sudo rabbitmqctl start_app
    

步骤4:验证集群形成

登录到节点A并验证两个节点是否相互识别。

rabbitmqctl cluster_status

预期输出片段:

你应该看到rabbitmq-node-arabbitmq-node-b都列在running_nodes下。

Cluster status of node rabbit@rabbitmq-node-a ...
[{nodes,[{disc,[rabbit@rabbitmq-node-a,rabbit@rabbitmq-node-b]}]},
 {running_nodes,[rabbit@rabbitmq-node-a,rabbit@rabbitmq-node-b]},
 ...
]

步骤5:配置队列的高可用性

标准的RabbitMQ集群共享元数据,例如用户、交换机、绑定和策略。如果你希望消息在节点故障时仍然存在,队列内容需要复制队列类型。

对于现代RabbitMQ部署,使用仲裁队列来实现复制的持久队列。在较旧的RabbitMQ版本中,经典镜像队列使用ha-mode策略,但该方法已被弃用,并从新的主要版本中移除。

声明一个仲裁队列

你可以从应用程序或使用rabbitmqadmin声明仲裁队列。此示例创建一个持久化的仲裁队列:

rabbitmqadmin declare queue name=orders durable=true arguments='{"x-queue-type":"quorum"}'

对于双节点实验室环境,仲裁队列可以运行,但它无法容忍丢失一个节点并仍然保持多数。对于生产环境,请至少使用三个RabbitMQ节点来运行仲裁队列,这样即使一个节点故障,队列仍然拥有多数节点。

步骤6:测试故障转移

在宣布集群就绪之前,测试客户端将使用的路径:

  1. 向仲裁队列发布几条持久化的测试消息。
  2. 使用sudo rabbitmqctl stop_app停止主节点的RabbitMQ应用程序。
  3. 确认客户端通过你的负载均衡器、DNS目标或服务发现设置重新连接。
  4. 从幸存节点消费测试消息。
  5. 使用sudo rabbitmqctl start_app再次启动已停止的应用程序,并检查rabbitmqctl cluster_status

最终总结

RabbitMQ集群为你提供共享的代理元数据,但队列的可用性取决于队列类型和客户端故障转移设计。使用仲裁队列实现复制的持久队列,至少保留三个节点以实现真正的容错,并使用应用程序使用的相同连接路径测试故障转移。