4. 集群基础:RabbitMQ 集群原理与搭建步骤

RabbitMQ 集群通过 Erlang 分布式协议将多个节点连接成一个逻辑整体,实现队列元数据、交换器、绑定关系的全局复制,从而突破单节点瓶颈,提供更高的吞吐量与可用性。本章深入剖析集群核心原理,并给出可复现的搭建步骤。

4.1 Erlang 分布式基础

RabbitMQ 基于 Erlang/OTP 构建,其集群本质上是 Erlang 节点间的分布式连接。每个 RabbitMQ 进程对应一个 Erlang 节点(rabbit@hostname),节点间通过 Erlang 分布式协议(EPMD)通信。

概念 说明
Erlang 节点 一个独立的 Erlang 虚拟机实例,拥有唯一名称 name@ip 或 name@host
EPMD Erlang Port Mapper Daemon,默认端口 4369,负责节点发现与端口映射
分布式连接 节点间通过 TCP 长连接交换消息,默认使用 全连接拓扑(每个节点与集群内所有其他节点直连)
Cookie 认证 所有节点必须使用相同的 .erlang.cookie 文件,否则无法建立连接
关键约束:Erlang 分布式要求节点间主机名可解析(DNS 或 /etc/hosts),且防火墙开放 EPMD 端口(4369)及节点间通信端口(默认范围 35672–35682)。

4.2 Cookie 同步机制

.erlang.cookie 是 Erlang 节点的共享密钥,位于 $HOME/.erlang.cookie(Linux)或 C:\Users\%USERNAME%\.erlang.cookie(Windows)。集群内所有节点必须持有完全相同的 Cookie 内容。

  • 生成时机:首次启动 RabbitMQ 时自动生成,随机 32 字符字符串。
  • 同步方法:
    1. 从已运行节点复制 Cookie 文件到新节点。
    2. 使用 rabbitmqctl set_cluster_name 或手动编辑文件。
    3. 重启 RabbitMQ 服务使新 Cookie 生效。
  • 权限要求:Cookie 文件权限必须为 400(仅属主可读),否则 Erlang 虚拟机拒绝启动。
常见错误:Cookie 不一致时,节点日志出现 Connection attempt from disallowed node 或 authentication failed。务必在加入集群前校验所有节点的 Cookie 内容。

4.3 节点发现与集群形成

RabbitMQ 支持两种节点发现模式:手动发现(传统方式)和 自动发现(基于插件)。

发现方式 原理 适用场景
手动发现 使用 rabbitmqctl join_cluster 指定已有节点 小规模集群(≤5 节点)、静态环境
DNS 发现 通过 DNS A/AAAA 记录解析集群节点列表 动态扩缩容、容器化部署
Consul/Etcd 发现 依赖外部服务注册中心 大规模生产集群、跨机房部署

集群形成后,节点间通过 Mnesia 数据库(Erlang 内置分布式 DB)同步元数据:交换器、队列绑定、虚拟主机、权限等。但 队列消息体本身不会跨节点复制——这是 RabbitMQ 集群与镜像队列/仲裁队列的核心区别。

RabbitMQ 集群节点发现与连接拓扑 RabbitMQ 集群节点发现与连接拓扑 Node A rabbit@node-a Node B rabbit@node-b Node C rabbit@node-c EPMD 发现层(端口 4369) DNS / Consul / 手动指定 共享 .erlang.cookie 认证 Mnesia 数据库同步元数据

4.4 集群搭建步骤(手动方式)

以下步骤基于 CentOS 7 / Ubuntu 22.04,使用三台主机(node-a, node-b, node-c)构建 3 节点集群。

4.4.1 环境准备

  1. 主机名与解析:确保每台机器的主机名唯一,且 /etc/hosts 包含所有节点 IP 映射。
  2. 防火墙:开放端口 4369(EPMD)和 35672–35682(节点间通信)。
  3. 安装 RabbitMQ:所有节点安装相同版本(推荐 3.12+)。
# 示例 /etc/hosts 配置(所有节点一致)
192.168.1.10 node-a
192.168.1.11 node-b
192.168.1.12 node-c

4.4.2 Cookie 同步

  1. 在 node-a 上查看 Cookie:cat /var/lib/rabbitmq/.erlang.cookie
  2. 将内容复制到 node-b 和 node-c 的相同路径。
  3. 设置权限:chmod 400 /var/lib/rabbitmq/.erlang.cookie
  4. 重启 RabbitMQ:systemctl restart rabbitmq-server

4.4.3 启动并加入集群

  1. 启动所有节点的 RabbitMQ 服务。
  2. 在 node-b 上执行:
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@node-a
rabbitmqctl start_app
  1. 在 node-c 上执行相同命令,目标节点仍为 rabbit@node-a。
  2. 在任意节点验证集群状态:
rabbitmqctl cluster_status

# 输出示例
Cluster status of node rabbit@node-a ...
Basics
Cluster name: rabbit@node-a
Disk Nodes
rabbit@node-a
rabbit@node-b
rabbit@node-c
Running Nodes
rabbit@node-a
rabbit@node-b
rabbit@node-c

4.4.4 设置集群名称(可选)

rabbitmqctl set_cluster_name "production-cluster-01"

4.5 集群验证与常用命令

命令 用途
rabbitmqctl cluster_status 查看集群节点列表、运行状态、分区状态
rabbitmqctl list_connections 查看客户端连接分布
rabbitmqctl list_queues 查看队列及其所在节点
rabbitmq-diagnostics check_port_connectivity 检测节点间端口连通性
rabbitmq-diagnostics erlang_cookie_sources 检查 Cookie 来源与一致性
生产建议:集群节点数建议为奇数(3、5、7),配合仲裁队列实现多数派选举,避免脑裂。首次搭建完成后,务必测试节点宕机与恢复场景,验证集群自愈能力。
RabbitMQ 集群搭建步骤流程图 RabbitMQ 集群搭建步骤流程 1. 环境准备 主机名 / 防火墙 / 安装 2. Cookie 同步 复制 .erlang.cookie 3. 启动服务 systemctl start 4. 加入集群 join_cluster 5. 启动应用 start_app 6. 验证状态 cluster_status 7. 重复节点 B、C 节点依次加入 所有节点加入完成后,集群自动形成全连接拓扑,Mnesia 同步元数据 建议使用 rabbitmqctl set_cluster_name 统一集群标识

4.6 集群关键特性与限制

  • 元数据全局复制:交换器、队列、绑定、用户、权限在所有节点一致。
  • 消息体单节点存储:队列消息只存在于声明该队列的节点,其他节点通过内部转发路由。
  • 客户端连接透明:生产者/消费者可连接任意节点,集群自动路由到目标节点。
  • 网络分区风险:节点间网络中断会导致集群分裂,需配置分区处理策略(pause-minority / autoheal)。
  • 节点类型:RAM 节点(元数据在内存)和 Disk 节点(元数据持久化),生产环境至少保留一个 Disk 节点。
核心结论:RabbitMQ 集群提供的是 元数据高可用,而非消息体高可用。要实现消息体跨节点冗余,必须使用镜像队列(经典版)或仲裁队列(现代推荐)。