☰
RabbitMQ集群搭建(二)
2026/11/1 1:32:14 网站建设 项目流程

简介

本文介绍如何搭建 RabbitMQ 集群,使用 RabbitMQ-3.8.34 版本

相关博客:

  • RabbitMQ集群搭建

环境规划

服务器清单如下,我在本地创建了如下三台虚拟机

IP 地址节点名称说明
192.168.249.137node1主节点,集群入口
192.168.249.138node2从节点
192.168.249.139node3从节点

服务器环境示意:

集群架构

  • 共 3 个 RabbitMQ 节点,采用镜像队列 / Quorum 队列实现高可用
  • 采用奇数节点数( 3 节点)避免脑裂问题
  • Quorum 队列基于 Raft 算法,至少需要 2 个节点在线才能正常工作

环境准备

Docker 环境

  • 所有服务器需提前安装 Docker 环境
  • 确认 Docker 服务正常运行:systemctl status docker

端口开放说明

RabbitMQ 集群需要开放以下端口:

  • 4369:epmd,节点发现服务
  • 5672:AMQP 协议,客户端连接端口
  • 15672:管理界面 Web 端口
  • 25672:节点间通信端口

搭建

(1)添加节点信息

在三台服务器上执行以下命令,添加节点 hosts 映射,保证节点间可通过名称互相访问:

cat>>/etc/hosts<<EOF 192.168.249.137 node1 192.168.249.138 node2 192.168.249.139 node3 EOF

配置完成示意:

(2)创建数据目录

为保证容器删除后数据不丢失,建议挂载数据卷:

# 在三台服务器分别执行mkdir-p/data/rabbitmq

(3)创建 RabbitMQ 容器

重要说明:所有节点必须使用相同的 Erlang Cookie才能加入同一集群。

节点1(192.168.249.137)

连接 192.168.249.137 执行下面的命令:

dockerrun-d\--hostnamenode1\--namerabbitmq\--net=host\--restart=always\-v/data/rabbitmq:/var/lib/rabbitmq\-eRABBITMQ_ERLANG_COOKIE="rabbitmq_cookie_123"\-eRABBITMQ_DEFAULT_USER=admin\-eRABBITMQ_DEFAULT_PASS=admin\rabbitmq:3.8.34-management

启动完成示意:


节点2(192.168.249.138)

连接 192.168.249.138 执行下面的命令:

dockerrun-d\--hostnamenode2\--namerabbitmq\--net=host\--restart=always\-v/data/rabbitmq:/var/lib/rabbitmq\-eRABBITMQ_ERLANG_COOKIE="rabbitmq_cookie_123"\-eRABBITMQ_DEFAULT_USER=admin\-eRABBITMQ_DEFAULT_PASS=admin\rabbitmq:3.8.34-management

启动完成示意:


节点 3(192.168.249.139)

连接 192.168.249.139 执行下面的命令:

dockerrun-d\--hostnamenode3\--namerabbitmq\--net=host\--restart=always\-v/data/rabbitmq:/var/lib/rabbitmq\-eRABBITMQ_ERLANG_COOKIE="rabbitmq_cookie_123"\-eRABBITMQ_DEFAULT_USER=admin\-eRABBITMQ_DEFAULT_PASS=admin\rabbitmq:3.8.34-management

启动完成示意:

(4)组建集群

以 node1 为主节点,将 node2 和 node3 加入到 node1 组成的集群中

连接 192.168.249.138 执行下面的命令,将节点 2 加入集群

# 停止节点应用dockerexecrabbitmq rabbitmqctl stop_app# 重置节点状态dockerexecrabbitmq rabbitmqctl reset# 加入到node1集群dockerexecrabbitmq rabbitmqctl join_cluster rabbit@node1# 重新启动应用dockerexecrabbitmq rabbitmqctl start_app

加入完成示意:


连接 192.168.249.139 执行下面的命令,将节点3加入集群

dockerexecrabbitmq rabbitmqctl stop_appdockerexecrabbitmq rabbitmqctl resetdockerexecrabbitmq rabbitmqctl join_cluster rabbit@node1dockerexecrabbitmq rabbitmqctl start_app

加入完成示意:

验证

(1) 查看集群状态

连接任意一个节点,执行以下命令查看集群状态:

dockerexecrabbitmq rabbitmqctl cluster_status

成功标志:三个节点都显示在running_nodes列表中

集群状态示意:

(2)管理控制台验证

通过浏览器访问任意节点的管理后台,使用账号密码admin/admin登录:

  • node1: http://192.168.249.137:15672
  • node2: http://192.168.249.138:15672
  • node3: http://192.168.249.139:15672

登录后在 “Nodes” 页面可以看到所有三个节点状态。

控制台示意:

(3) 高可用验证(Quorum 队列)

RabbitMQ 3.8+ 推荐使用Quorum 队列替代传统镜像队列:

特性普通队列镜像队列Quorum 队列
高可用❌ 单点✅ 主从复制✅ Raft算法
数据一致性-最终一致强一致
脑裂问题-可能发生不会发生
最小节点数123(建议奇数)

(4)故障转移测试

# 1. 停掉一个节点dockerstop rabbitmq# 2. 在其他节点查看集群状态,确认队列仍可用dockerexecrabbitmq rabbitmqctl cluster_status# 3. 重启节点,观察是否自动重新加入集群dockerstart rabbitmq

项目整合

(1) 配置文件修改

原单机配置:

spring:rabbitmq:host:${rabbitmq.ip}port:${rabbitmq.port}username:${rabbitmq.username}password:${rabbitmq.password}template:reply-timeout:30000listener:simple:missing-queues-fatal:false

修改为集群配置,配置所有节点地址:

spring:rabbitmq:addresses:192.168.249.137:5672,192.168.249.138:5672,192.168.249.139:5672username:${rabbitmq.username}password:${rabbitmq.password}template:reply-timeout:30000listener:simple:missing-queues-fatal:false

配置建议:将全部 3 个节点都写入配置,作为集群入口。只配置少数节点时,若这些入口节点同时宕机,即使集群本身仍可用,应用也无法连接。


(2)Java 代码修改

a. ConnectionFactory Bean 初始化

如果你的项目中,使用了手动初始化 RabbitMQ 的连接工厂,需要做以下修改

原代码:

@Value("${rabbitmq.ip}")privateStringhost;@Value("${rabbitmq.port}")privateintport;@Value("${rabbitmq.username}")privateStringusername;@Value("${rabbitmq.password}")privateStringpassword;@Value("${rabbitmq.cache_size}")privateintcacheSize;@BeanpublicConnectionFactoryrabbitMQConnectionFactory(){CachingConnectionFactoryconnectionFactory=newCachingConnectionFactory();connectionFactory.getRabbitConnectionFactory().setRequestedChannelMax(10240);connectionFactory.setHost(host);connectionFactory.setPort(port);connectionFactory.setUsername(username);connectionFactory.setPassword(password);connectionFactory.setChannelCacheSize(cacheSize);connectionFactory.setChannelCheckoutTimeout(2000);connectionFactory.getRabbitConnectionFactory().setAutomaticRecoveryEnabled(true);connectionFactory.getRabbitConnectionFactory().setNetworkRecoveryInterval(10000);connectionFactory.getRabbitConnectionFactory().setTopologyRecoveryEnabled(true);returnconnectionFactory;}

修改后,改用集群地址配置:

@Value("${spring.rabbitmq.addresses}")privateStringaddresses;@Value("${spring.rabbitmq.username}")privateStringusername;@Value("${spring.rabbitmq.password}")privateStringpassword;@Value("${rabbitmq.cache_size}")privateintcacheSize;@BeanpublicConnectionFactoryrabbitMQConnectionFactory(){CachingConnectionFactoryconnectionFactory=newCachingConnectionFactory();connectionFactory.getRabbitConnectionFactory().setRequestedChannelMax(10240);connectionFactory.setAddresses(addresses);// 使用 addresses 替代 hostconnectionFactory.setUsername(username);connectionFactory.setPassword(password);connectionFactory.setChannelCacheSize(cacheSize);connectionFactory.setChannelCheckoutTimeout(2000);connectionFactory.getRabbitConnectionFactory().setAutomaticRecoveryEnabled(true);connectionFactory.getRabbitConnectionFactory().setNetworkRecoveryInterval(10000);connectionFactory.getRabbitConnectionFactory().setTopologyRecoveryEnabled(true);returnconnectionFactory;}
b. 创建队列(非注解方式)- 使用 Quorum 队列

原代码:

@BeanpublicQueuetestQueue(){returnnewQueue("testQueue",true);}

修改为Quorum队列,保证高可用:

@BeanpublicQueuetestQueue(){returnQueueBuilder.durable("testQueue").quorum()// 声明为Quorum队列.build();}
c. 创建队列(注解方式)- 使用 Quorum 队列

原代码:

@RabbitListener(bindings=@QueueBinding(value=@Queue(value="testQueue",autoDelete="false"),exchange=@Exchange(value="testExchange",type=ExchangeTypes.TOPIC)),containerFactory="rabbitMQConnectionFactory")

修改后,增加x-queue-type参数声明为 Quorum 队列:

@RabbitListener(bindings=@QueueBinding(value=@Queue(value="testQueue",autoDelete="false",arguments=@Argument(name="x-queue-type",value="quorum")),exchange=@Exchange(value="testExchange",type=ExchangeTypes.TOPIC)),containerFactory="rabbitMQConnectionFactory")

注意事项

  1. Erlang Cookie一致:所有节点的 Cookie 必须完全相同,否则无法加入集群

  2. 主机名解析:确保所有节点能通过 hostname 互相访问,/etc/hosts配置必须一致

  3. Quorum 队列节点数:Quorum 队列基于 Raft 算法,至少需要(N/2)+1个节点在线才能写入。3 节点集群最多允许 1 个节点宕机

  4. 数据持久化:生产环境务必挂载数据卷,防止容器删除导致数据丢失

  5. 防火墙配置:开放 4369、5672、15672、25672 四个端口

  6. 密码安全:生产环境建议修改默认的 admin/admin 密码

  7. 监控告警:建议监控队列堆积、节点状态、连接数等指标

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询