Docker 部署 RabbitMQ 集群

264 阅读5分钟

一、环境准备

构建环境

操作系统:ubuntu24.04.1 LTS

Docker版本:27.5.1

修改主机名

主机名不能相同

 hostnamectl set-hostname node1         192.168.59.128
 hostnamectl set-hostname node2		192.168.59.129
 hostnamectl set-hostname node3		192.168.59.130

设置主机名解析(每台服务器执行)

cat <<EOF | sudo tee -a /etc/hosts
192.168.59.128 node1
192.168.59.129 node2
192.168.59.130 node3
EOF

# 验证解析:
ping node2  # 在所有节点应能解析

开放必要端口

sudo ufw allow 4369/tcp  # Erlang 端口映射
sudo ufw allow 5672/tcp  # AMQP
sudo ufw allow 15672/tcp # 管理界面
sudo ufw allow 25672/tcp # Erlang 分布式节点
sudo ufw reload

创建共享配置文件(所有服务器)

# 创建配置目录
mkdir -p ~/rabbitmq/config

# 创建 rabbitmq.conf 配置文件
cat <<EOF > ~/rabbitmq/config/rabbitmq.conf
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@node1
cluster_formation.classic_config.nodes.2 = rabbit@node2
cluster_formation.classic_config.nodes.3 = rabbit@node3

loopback_users = none
management.tcp.port = 15672
management.tcp.ip = 0.0.0.0  # 确保绑定所有接口
EOF

# 创建相同的 Erlang cookie(必须完全一致!)
echo "MY_SECRET_COOKIE" > ~/rabbitmq/.erlang.cookie
chmod 600 ~/rabbitmq/.erlang.cookie

拉取镜像

docker pull rabbitmq:3.13-management

二、搭建RabbitMQ集群

在 rabbitmq1 (192.168.59.128):

docker run -d \
  --name rabbitmq1 \
  --network host \
  --add-host=node1:192.168.59.128 \
  --add-host=node2:192.168.59.129 \
  --add-host=node3:192.168.59.130 \
  -p 5672:5672 \
  -p 15672:15672 \
  -v ~/rabbitmq/config:/etc/rabbitmq \
  -v ~/rabbitmq/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
  -e RABBITMQ_NODENAME=rabbit@node1 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=adminpassword \
  rabbitmq:3.13-management

在 rabbitmq2 (192.168.59.129):

docker run -d \
  --name rabbitmq2 \
  --network host \
  --add-host=node1:192.168.59.128 \
  --add-host=node2:192.168.59.129 \
  --add-host=node3:192.168.59.130 \
  -p 5672:5672 \
  -p 15673:15672 \
  -v ~/rabbitmq/config:/etc/rabbitmq \
  -v ~/rabbitmq/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
  -e RABBITMQ_NODENAME=rabbit@node2 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=adminpassword \
  rabbitmq:3.13-management

在 rabbitmq3 (192.168.59.130):

docker run -d \
  --name rabbitmq3 \
  --network host \
  --add-host=node1:192.168.59.128 \
  --add-host=node2:192.168.59.129 \
  --add-host=node3:192.168.59.130 \
  -p 5672:5672 \
  -p 15674:15672 \
  -v ~/rabbitmq/config:/etc/rabbitmq \
  -v ~/rabbitmq/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
  -e RABBITMQ_NODENAME=rabbit@node3 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=adminpassword \
  rabbitmq:3.13-management

三、验证集群状态

在node1节点执行

docker exec rabbitmq1 rabbitmqctl cluster_status

应看到类似输出:

# Cluster status of node rabbit@rabbitmq1
# [{nodes,[{disc,[rabbit@rabbitmq1,rabbit@rabbitmq2,rabbit@rabbitmq3]}]},
# {running_nodes,[rabbit@rabbitmq3,rabbit@rabbitmq2,rabbit@rabbitmq1]}]

四、配置高可用(镜像集群)

在任意节点执行策略配置

docker exec rabbitmq1 rabbitmqctl set_policy ha-all "^" \
  '{"ha-mode":"all","ha-sync-mode":"automatic"}'

验证策略

docker exec rabbitmq1 rabbitmqctl list_policies

输出应包含:

root@node1:~# docker exec rabbitmq1 rabbitmqctl list_policies
Listing policies for vhost "/" ...
vhost   name    pattern apply-to        definition      priority
/       ha-all  ^       all     {"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}  0

五、访问管理界面

启用插件

docker exec rabbitmq1 rabbitmq-plugins enable rabbitmq_management
docker exec rabbitmq2 rabbitmq-plugins enable rabbitmq_management
docker exec rabbitmq3 rabbitmq-plugins enable rabbitmq_management

访问任意节点的管理界面:

http://192.168.59.128:15672/#/
http://192.168.59.129:15672/#/
http://192.168.59.130:15672/#/

使用账号:admin 密码:adminpassword

六、验证消息同步

  1. 创建测试队列
    1. 点击顶部菜单“Queues”
    2. 点击“Add a new Queue”
    3. 输入参数Name:“mirror_test_queue”、Durability: Durable (持久化)、Arguments: 留空
    4. 点击 "Add queue"
  1. 发送测试消息
    1. 在队列列表中找到 mirror_test_queue,点击进入详情页
    2. 滚动到 "Publish message" 区域
    3. 输入消息内容:
{
  "text": "Hello from node1!",
  "timestamp": "2025-07-23T10:00:00Z"
}
    1. 点击 "Publish Message"
  1. 验证消息同步
    1. 方法一:查看所有节点的队列状态,
节点	访问地址								检查位置				预期结果
node1	http://192.168.59.128:15672	Queues → mirror_test_queue	Ready: 1 条消息
node2	http://192.168.59.129:15673	Queues → mirror_test_queue	Ready: 1 条消息
node3	http://192.168.59.130:15674	Queues → mirror_test_queue	Ready: 1 条消息
    1. 方法二:在任意节点的队列详情页:
      1. 找到 "Mirrors" 区域
      2. 检查所有节点状态:1 个节点标记为 master(主节点)、其他节点标记为 mirror(镜像节点)
  1. 模拟主节点故障
    1. 停止主节点容器(假设主节点是 node1):docker stop rabbitmq1
    2. 等待 10 秒,RabbitMQ 会自动选举新主节点
    3. 访问存活节点的管理界面(如 http://192.168.59.129:15673)
    4. 检查:
      1. 队列 mirror_test_queue 依然存在
      2. 消息数量仍为 1
      3. 新主节点显示在 "Mirrors" 顶部
    1. 消费消息验证
      1. 在任意存活节点执行,在队列详情页滚动到 "Get messages" 区域
      2. 点击 "Get Message(s)"
      3. 查看返回的消息内容应与发送的一致

七、故障排查

  1. 节点无法加入集群
    1. 检查所有节点的 .erlang.cookie 文件内容完全一致
    2. 验证主机名解析:docker exec rabbitmq1 ping rabbitmq2
    3. 检查防火墙开放端口:4369, 25672 bash
# 检查cookie一致性
docker exec rabbitmq1 cat /var/lib/rabbitmq/.erlang.cookie
docker exec rabbitmq2 cat /var/lib/rabbitmq/.erlang.cookie
docker exec rabbitmq3 cat /var/lib/rabbitmq/.erlang.cookie

# 测试容器间网络
docker exec rabbitmq1 ping node2
docker exec rabbitmq1 ping node3

# 检查端口连通性(在node1上测试node2)
telnet node2 4369
telnet node2 25672
  1. Web 界面无法访问
# 检查容器状态
docker ps -a | grep rabbitmq

# 查看容器日志
docker logs rabbitmq1

# 检查服务状态
docker exec rabbitmq1 rabbitmqctl status
  1. 节点状态不一致
# 重置节点(在问题节点执行)
docker exec rabbitmq2 rabbitmqctl stop_app
docker exec rabbitmq2 rabbitmqctl reset
docker exec rabbitmq2 rabbitmqctl join_cluster rabbit@node1
docker exec rabbitmq2 rabbitmqctl start_app
  1. 应用未启动
# 手动启动应用(所有节点)
docker exec rabbitmq1 rabbitmqctl start_app
docker exec rabbitmq2 rabbitmqctl start_app
docker exec rabbitmq3 rabbitmqctl start_app
  1. 容器启动后自动退出
# 查看容器日志
docker logs rabbitmq1

# 常见原因:
# 1. cookie权限问题:确保宿主机cookie文件权限为600
# 2. 端口冲突:检查4369、25672端口是否被占用
# 3. 主机名解析失败:确保容器内能解析node1/node2/node3