RabbitMQ 集群
单节点 RabbitMQ 受制于单机吞吐与故障面:节点挂了服务就断。集群把多个节点组成一个逻辑 broker,可横向扩展吞吐,配合高可用队列(见下章)还能在节点故障时继续对外服务。
为什么需要集群
- 提升吞吐:多个节点分摊连接与路由压力;
- 高可用:节点宕机时其它节点接管服务(前提是队列有副本,否则队列仍不可用);
- 统一管理:一个集群一套账号权限、一个管理台。
节点类型:内存节点与磁盘节点
集群节点按元数据存储方式分为两类:
| 类型 | 元数据存放 | 说明 |
|---|---|---|
| 磁盘节点 disc | 磁盘(默认) | 持久保存队列、交换机、绑定、用户等定义 |
| 内存节点 ram | 仅内存 | 重启后从磁盘节点同步,读写略快 |
集群必须至少保留一个磁盘节点来保存定义;生产环境建议全部使用磁盘节点,ram 节点只在特殊压测场景考虑。
组集群步骤
假设 node1 已运行,把 node2 加入组成两节点集群:
# 1. 在两台机器上保证 Erlang Cookie 一致:
# 把 node1 的 /var/lib/rabbitmq/.erlang.cookie 复制到 node2,
# 保持属主为 rabbitmq、权限 400,然后重启 node2 的 rabbitmq
# 2. 在 node2 上依次执行:
rabbitmqctl stop_app
rabbitmqctl reset # 清空 node2 独立的旧状态
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app
rabbitmqctl cluster_status
# 输出:Running Nodes: rabbit@node1 rabbit@node2
# Partitions: [] # 无网络分区
Erlang Cookie 不一致时节点间认证失败,报 Node authentication failure 之类的错;join 前还要保证两边主机名能互相解析。让节点离开集群:本机 stop_app 后 reset 自退,或在其它节点上执行 rabbitmqctl forget_cluster_node rabbit@node2。
想在一台机器上模拟多节点实验,可用不同的 RABBITMQ_NODE_NAME 与 RABBITMQ_NODE_PORT(如 rabbit1@localhost:5673、rabbit2@localhost:5674)启动多个实例组集群,仅适合学习。
集群中的队列归属
集群共享交换机、绑定、队列元数据与账号权限(由磁盘节点持久化),但经典队列的"消息本体"默认只存在声明它的那个节点上,即队列主节点:
- 消费者连哪个节点都能收发,broker 内部会把请求路由到队列所在节点;
- 主节点宕机时,其上单副本队列的消息会暂时不可用,直到节点恢复;
- 想让消息也有副本,需要镜像队列或仲裁队列(见下章)。
集群通信端口
| 端口 | 用途 |
|---|---|
| 4369 | epmd 节点发现 |
| 25672 | 节点间集群通信 |
| 5672 | AMQP 客户端连接 |
| 15672 | 管理台与 HTTP API |
集群节点之间至少放通 4369 与 25672,云上部署还要检查安全组。
集群边界:federation 与 shovel
集群解决"同一逻辑集群内多节点"的扩展与高可用;跨集群(异地机房、异构环境)的数据迁移属于另一类工具:federation 按需把上游消息转发到下游,shovel 固定搬运某条链路。它们解决跨集群复制,替代不了集群内的队列副本。
小结
集群 = 统一逻辑 broker + 水平扩展:节点间靠一致的 Erlang Cookie 互信,stop_app → reset → join_cluster → start_app 即可加入,cluster_status 确认状态。记住默认队列是单副本这一前提,高可用必须靠镜像或仲裁队列补上。