3. 集群基础模式:普通集群(Classic Cluster)的搭建、节点发现与元数据同步机制
普通集群(Classic Cluster)是 RabbitMQ 最基础的分布式部署形态。它通过将多个 Erlang 节点连接成一个逻辑集群,实现队列元数据、交换器、绑定关系、虚拟主机、用户权限等信息的全局共享。本章将深入讲解普通集群的搭建步骤、节点发现机制以及元数据同步的核心原理。
3.1 普通集群架构概览
在普通集群中,所有节点共享 逻辑集群名称 和 Erlang Cookie。集群内的每个节点都保存一份完整的元数据副本(包括交换器、绑定、虚拟主机、用户等),但队列的消息体只存储在声明该队列的节点上,其他节点仅持有该队列的元数据指针和路由信息。
关键理解: 普通集群中,元数据全量同步,消息体按需路由。消费者连接到非队列主节点时,该节点会通过内部 Erlang 通信将请求转发到队列所在节点,这称为内部路由转发。
3.2 普通集群搭建步骤
搭建普通集群需要准备至少两台主机(或容器),确保它们之间网络互通,且 Erlang Cookie 一致。以下是基于三节点集群的搭建流程:
3.2.1 前置条件
- 主机名解析: 所有节点的主机名必须能够互相解析(推荐使用 /etc/hosts 或 DNS)。
- Erlang Cookie 一致: 将主节点的
.erlang.cookie文件(通常位于/var/lib/rabbitmq/.erlang.cookie)复制到所有从节点,权限设为 400。 - 端口开放: 确保 4369(EPMD)、5672(AMQP)、25672(Erlang 分布式端口)等端口可互通。
3.2.2 搭建步骤
| 步骤 | 操作 | 命令/说明 |
|---|---|---|
| 1 | 启动各节点 RabbitMQ 服务 | systemctl start rabbitmq-server 或 rabbitmq-server -detached |
| 2 | 停止应用(保留 Erlang 节点) | rabbitmqctl stop_app |
| 3 | 重置节点状态 | rabbitmqctl reset(仅从节点执行) |
| 4 | 加入集群 | rabbitmqctl join_cluster rabbit@node1(从节点执行) |
| 5 | 启动应用 | rabbitmqctl start_app |
| 6 | 验证集群状态 | rabbitmqctl cluster_status |
示例: 将 node2 和 node3 加入以 node1 为种子节点的集群:
# 在 node2 上执行
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app
# 在 node3 上执行
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app
# 在任意节点查看集群状态
rabbitmqctl cluster_status
3.3 节点发现机制
RabbitMQ 普通集群的节点发现主要依赖 Erlang 分布式协议 和 EPMD(Erlang Port Mapper Daemon)。节点发现过程分为两个阶段:
3.3.1 发现流程
- 种子节点连接: 执行
join_cluster时,从节点通过 EPMD 查询种子节点的 Erlang 分布式端口(默认 25672)。 - 握手与认证: 双方交换 Erlang Cookie 进行身份验证。Cookie 一致则建立加密连接。
- Mnesia 同步: 新节点从种子节点拉取完整的元数据副本,并注册到集群成员列表。
- 心跳维护: 节点间通过 net_ticktime(默认 60 秒)发送心跳,检测节点存活状态。
3.3.2 节点发现参数
| 参数 | 默认值 | 说明 |
|---|---|---|
net_ticktime |
60 | 节点心跳间隔(秒),影响故障检测速度 |
cluster_formation.peer_discovery_backend |
rabbit_peer_discovery_classic_config | 节点发现后端,支持 DNS、AWS、K8s 等 |
cluster_formation.node_cleanup.interval |
30 | 清理失联节点信息的间隔(秒) |
3.4 元数据同步机制
普通集群的元数据同步基于 Erlang 的 Mnesia 分布式数据库。Mnesia 是一个实时、内存/磁盘混合的分布式 DBMS,RabbitMQ 利用它存储所有逻辑配置信息。
3.4.1 同步内容
- 交换器(Exchange): 名称、类型、属性、绑定关系。
- 队列(Queue): 名称、属性、绑定关系(不含消息体)。
- 绑定(Binding): 交换器与队列的关联规则。
- 虚拟主机(VHost): 隔离环境配置。
- 用户与权限: 认证与授权信息。
- 运行时参数: 策略(Policy)、参数(Parameter)等。
3.4.2 同步方式
| 同步类型 | 触发条件 | 行为描述 |
|---|---|---|
| 全量同步 | 节点加入集群 | 新节点从种子节点拉取所有 Mnesia 表数据 |
| 增量同步 | 元数据变更(创建/删除/修改) | 变更节点通过 Mnesia 事务广播到所有在线节点 |
| 定期同步 | 节点重连或网络分区恢复 | Mnesia 自动对比表版本,同步差异数据 |
重要限制: 普通集群不提供队列消息体的高可用。如果队列所在节点宕机,该队列的消息将丢失,直到节点恢复。需要消息高可用时,应使用镜像队列(Mirrored Queues)或 Quorum Queues。
3.5 集群管理与验证
3.5.1 常用管理命令
# 查看集群状态
rabbitmqctl cluster_status
# 查看集群节点列表
rabbitmqctl list_nodes
# 移除节点(需在目标节点执行)
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
# 强制移除失联节点(在存活节点执行)
rabbitmqctl forget_cluster_node rabbit@node3
3.5.2 验证集群功能
- 元数据同步验证: 在 node1 创建交换器
test.exchange,在 node2 和 node3 上通过rabbitmqctl list_exchanges确认可见。 - 路由转发验证: 在 node1 声明队列
test.queue,在 node2 上绑定并发送消息,确认消费者在 node3 上能正常消费。 - 故障转移验证: 停止 node1 的 RabbitMQ 服务,检查 node2 和 node3 的集群状态,确认节点被标记为
down。
生产建议: 普通集群至少部署 3 个节点,以应对单节点故障时的元数据可用性。同时,建议将
net_ticktime 调整为 10-30 秒,加快故障检测速度。