目录
引言
在现代分布式系统中,消息队列(Message Queue)扮演着至关重要的角色,而 RabbitMQ 作为最流行的开源消息代理之一,广泛应用于异步通信、任务队列、事件驱动架构等场景。然而,单节点的 RabbitMQ 存在单点故障(SPOF, Single Point of Failure)风险,一旦宕机,整个消息系统就会瘫痪。因此, 搭建 RabbitMQ 集群 成为保障系统高可用性(High Availability, HA)和负载均衡(Load Balancing)的关键措施。
为了保证MQ 中间件的可靠性、并发性、吞吐量,在生产环境上一般都会考虑使用 RabbitMQ 的集群方案。当然本搭建过程只是用于测试阶段,如用于上线产品,需要更严格的搭建流程。
一、环境准备
本搭建过程搭建需要四台虚拟机,同时他们都已经安装了相同版本的RabbitMQ,我建议是由一台主用虚拟机,克隆复制出另外三台。完成后如下:
使用远程连接工具:finalshell
二、利用虚拟机搭建
这里利用我本地的虚拟机模拟三台真实的机器
服务器信息表:
IP地址 | 主机名 | 操作系统 |
---|---|---|
192.168.93.135 | rabbitmq01 | CentOS7(64位) |
192.168.93.136 | rabbitmq02 | CentOS7(64位) |
192.168.93.137 | rabbitmq03 | CentOS7(64位) |
进行下一步前可以在本地windows的cmd中测试ping一下上面的三个虚拟机的IP地址。如果都能ping通,那可以进行下一步。
(1)下面修改三台机器的hosts配置文件,为了方便机器间的相互访问,三台centos都执行 vim /etc/hosts , 添加下边的配置,依次执行:
bash
#将三台机器上hosts都修改内容如下
vim /etc/hosts
192.168.93.135 rabbitmq01
192.168.93.136 rabbitmq02
192.168.93.137 rabbitmq03
#通过ping命令看主机名是否生效
ping rabbitmq02
#修改三台主机的主机名 vim /etc/hostname
#修改主机名会导致这台主机上RabbitMQ的数据丢失,可以只改后两台主机名,或者修改前备份
#rabbitmq01 修改为 rabbitmq01.localdomain
#rabbitmq02 修改为 rabbitmq02.localdomain
vim /etc/hostname
#然后重启每台机器
reboot
对应修改如下:
(2)如果上述都已准确完成,进行下一步:
保持三台机器的.erlang.cookie 内容一致
这个cookie 存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是 400 的权限
必须保证各节点cookie 一致 , 才能使节点之间相互通信
例如: 全部使用 rabbitmq01 的 /.erlang.cookie
bash
#查看rabbitmq01的.erlang.cookie
cat erlang.cookie
#修改rabbitmq02和rabbitmq03的.erlang.cookie
vim /var/lib/rabbitmq/.erlang.cookie
#该文件是只读的,加上写权限
chmod u+w /var/lib/rabbitmq/.erlang.cookie
vim /var/lib/rabbitmq/.erlang.cookie

将另外两台都改成与这一样的即可。
最后启动三台机器上的rabbitMQ服务
bash
#每台机器的RabbitMQ服务的访问地址和控制台的访问地址分别是
#192.168.93.135:5672 192.168.93.135:15672
#192.168.93.136:5672 192.168.93.136:15672
#192.168.93.137:5672 192.168.93.137:15672
#启动RabbitMQ服务
service rabbitmq-server start
(3)将rabbitmq02,rabbitmq03作为内存节点加入rabbitmq01节点集群中

开放端口:
bash
#这里需要开放25672和4369
firewall-cmd --zone=public --add-port=25672/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
firewall-cmd --zone=public --add-port=4369/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
在进行操作:
bash
#在rabbitmq02机器下执行
#停掉rabbit应用
rabbitmqctl stop_app
#加入rabbitmq01
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
#启动rabbit应用
rabbitmqctl start_app
#查看所有节点状态
rabbitmqctl cluster_status
最后查看所有节点状态时:

到此:
三、镜像集群配置
上面已经完成RabbitMQ 默认集群模式,但并不保证队列的高可用性,尽管队列 , 交换机 , 绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制.
为了保证队列中的内容也能复制, 要使用镜像队列 , 镜像队列再添加一些策略。
在网页上打开三个虚拟机的任意一个RabbitMQ的控制台,按照以下添加策略:

当然如果不想用上面的方式,可以执行下面一行命令来完成操作(任意虚拟机即可):
bash
策略参数解读:
# ha-all:为策略名称;
# ^my:为匹配符,只有一个^代表匹配所有,^abc为匹配名称以abc开头的queue或exchange,^.则
匹配所有
# ha-mode:为同步模式,一共3种模式:
# all-所有(所有的节点都同步消息),
# exctly-指定节点的数目(需配置ha-params参数,此参数为int类型比如2,在集群中随机
抽取2个节点同步消息)
# nodes-指定具体节点(需配置ha-params参数,此参数为数组类型比如
["rabbit@rabbitmq01","rabbit@rabbitmq02"],明确#指定在这两个节点上同步消息)。
# ha-sync-mode
#ha-sync-mode=manual(默认),镜像队列中的消息不会主动同步到新节点,除非显式调用同步命令,
调用同步命令后,队列开始阻塞,无法对其进行操作,直到同步完毕
#ha-sync-mode=automatic 新加入节点时会默认同步已知的镜像队列
#执行该命令等效于上面的页面添加策略操作
rabbitmqctl set_policy ha-all "^." '{"ha-mode":"all","ha-sync-mode":"automatic"}'
测试:
bash
#关闭rabbitmq01
rabbitmqctl stop_app

四、HAProxy****实现负载均衡(主用虚拟机操作)
HAProxy提供高可用性、负载均衡以及基于 TCP 和 HTTP 应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案, 包括 Twitter , Reddit , StackOverflow , GitHub 在内的多家知名互联网公司在使用。HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。
安装HAProxy:
bash
yum install -y haproxy
haproxy -v
看到下面则安装成功:
在 HAProxy 的 /etc/haproxy/haproxy.cfg 中添加如下配置:
bash
### haproxy 监控页面地址是:http://192.168.93.134:9188/haproxy_status
listen admin_stats
bind *:9188
mode http
log 127.0.0.1 local3 err
stats refresh 60s
stats uri /haproxy_status
stats realm welcome login\ Haproxy
stats auth admin:123456 ##记得改成自己的账号和密码
stats hide-version
stats admin if TRUE
### rabbitmq 集群配置,转发到
listen rabbitmq_cluster
bind *:5672
mode tcp
balance roundrobin
server rabbitnode1 192.168.93.135:5672 check inter 2000 rise 2 fall 3 weight 1
server rabbitnode2 192.168.93.136:5672 check inter 2000 rise 2 fall 3 weight 1
server rabbitnode3 192.168.93.137:5672 check inter 2000 rise 2 fall 3 weight 1
添加后:

完成上述的修改和配置后,启动
bash
haproxy -f /etc/haproxy/haproxy.cfg
在网页上访问:http://192.168.93.134:9188/haproxy_status
看到下图,说明已经配置成功:

可以看到三个虚拟机已经和HAProxy实现了负载均衡,当有信息发送到三台主机中的任意一个rabbitMQ时,尽管两外一台或两台出现宕机的情况,仍然不妨碍我们使用。
五、测试RabbitMQ****集群搭建情况
完成上面的所有配置后,下面使用IDEA来连接RabbitMQ测试搭建情况:
连接三台中任意一台虚拟机即可:
bash
public class SimpleProducer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂,并且设置RabbitMQ相关的连接参数
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("192.168.93.135");
connectionFactory.setPort(5672); //设置rabbitMq的默认端口 不修改可以不设置
//connectionFactory.setUsername("admin");
//connectionFactory.setPassword("123456");
//connectionFactory.setVirtualHost("myVH");
//2.根据连接工厂创建一个连接,根据这个连接创建一个channel
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
//3.创建一个队列(Queue)
//设置队列名、是否持久化、是否独占、是否被消费后自动删除、队列参数等等
channel.queueDeclare("hello",true,false,false,null);
//4.发布一条消息
//设置交换机名称、routingKey、信息属性、消息内容
channel.basicPublish("","hello",null,"Hello,World".getBytes());
//5.释放资源
channel.close();
connection.close();
}
}
发送信息后,查看任意页面:

当故意关闭三台中的任意一台或两台虚拟机(模拟宕机)时,仍可以继续发送信息,再次启动"宕机"的虚拟机,会自动同步消息,应为三台机器已经构成一个集群,可以实现信息互相同步,当出问题时,信息会立刻同步到正常的机器上去,宕机修复后又可以同步,这里不再演示此过程。