📣读完这篇文章里你能收获到
- RabbitMQ多种模式的区别及概念
- 手把手带你搭建高可用集群
- 接入HaProxy做高可用负载均衡
- 针对生产突发的异常场景提进行测试验证
一、概念篇
- MQ 会导致系统可用性降低。所以只要你用了 MQ,肯定就要想着 MQ 的缺点怎么来解决了,要是你傻乎乎的就干用了一个 MQ,各种问题从来没考虑过,那你就杯具了。
- RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的
- RabbitMQ 有三种模式:
单机模式
、普通集群模式
、镜像集群模式
1 单机模式
单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的😄,没人生产用单机模式。
2 普通集群模式(无高可用性)
普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。
这种方式确实很麻烦,也不怎么好,没做到所谓的分布式
,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个 queue 所在实例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。
而且如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让 RabbitMQ 落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个 queue 拉取数据。
所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性,这方案主要是提高吞吐量
的,就是说让集群中多个节点来服务某个 queue 的读写操作。
3 镜像集群模式(高可用性)
这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。
那么如何开启这个镜像集群模式呢?其实很简单,RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!第二,这么玩儿,不是分布式的,就没有扩展性可言了,如果某个 queue 负载很重,你加机器,新增的机器也包含了这个 queue 的所有数据,并没有办法线性扩展你的 queue。你想,如果这个 queue 的数据量很大,大到这个机器上的容量无法容纳了,此时该怎么办呢?大家自己动脑筋想一下吧,有好思路(别跟我说换Kafka可以解决,我也知道)欢迎评论
。
二、普通集群搭建
rabbitmq镜像集群依赖于普通集群,所以需要先搭建rabbitmq普通集群
1 构建环境
操作系统:Centos7
Docker版本:20.10.5
2 搭建RabbitMQ普通集群
- docker拉取带management tag的最新版本
docker pull rabbitmq:management
- 启动并创建三个同样cookie的镜像实例(同样的cookie才能加入集群)
这里注意使用--link将容器实例之前网络联系起来
docker run -d --hostname rabbit1 --name myrabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
docker run -d --hostname rabbit2 --name myrabbit2 -p 15673:15672 -p 5673:5672 --link myrabbit1:rabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
docker run -d --hostname rabbit3 --name myrabbit3 -p 15674:15672 -p 5674:5672 --link myrabbit1:rabbit1 --link myrabbit2:rabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
- 两个从机加入集群
docker exec -it myrabbit1 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit
docker exec -it myrabbit2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
exit
docker exec -it myrabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
exit
- 测试普通集群是否搭建成功
进入控制台web界面查看http://ip:15672
, 可以发现普通集群搭建成功
//其他基本操作
// 在另外其他节点上操作要移除的集群节点
rabbitmqctl forget_cluster_node master73@master73
//集群名称(默认为第一个node名称)修改(任意节点):
rabbitmqctl set_cluster_name rabbitmq_cluster1
//查看集群状态(任意节点)
rabbitmqctl cluster_status
三、镜像集群配置
1 通过命令配置
- 设置镜像队列策略(在任意一个节点上执行)
docker exec -it myrabbit1 bash
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
2 通过Dashboard控制台手动配置
切换到Admin->Policy->Add/Update Policy![]()
参数含义:
pattern: 队列名字的通配符
ha-mode:镜像队列提供了三种模式:
- all:全部的节点队列都做镜像;
- exactly:指定镜像队列的节点最高镜像数量;
- nodes:只为指定具体节点配置镜像队列;
ha-sync-mode :节点之前的同步模式。有自动和手动两种,默认是手动,这里设置为自动。
3 查看镜像队列配置
设置完成并添加了这个策略后,新建的和已存在的队列默认会支持此策略
队列会被同步复制到各个节点,RabbitMQ高可用集群就已经搭建好了
四、接入HaProxy做高可用负载均衡
HaProxy是一款提供高可用性、负载均衡以及基于TCP(第四层)和HTTP(第七层)应用的代理软件,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HaProxy特别适用于负载特大的web站点,这些站点通常又需要会话保持或七层处理。HaProxy运行在时下的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以简单安全整合进您当前框架中,同时可以保护你的web服务器不被暴露到网络上。
1 拉取HaProxy镜像
docker pull haproxy
2 创建haproxy.cfg配置文件
mkdir /project/haproxy/
vi /project/haproxy/haproxy.cfg
- 这里一定要注意,创建的名字一定要为
haproxy.cfg
,不然后面挂载的时候一直报错
haproxy.cfg文件内容
global
log 127.0.0.1 local0 info
maxconn 5120
uid 99
gid 99
daemon
quiet
nbproc 20
defaults
log global
#使用4层代理模式,”mode http”为7层代理模式
mode tcp
#if you set mode to tcp,then you nust change tcplog into httplog
option tcplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5s
#客户端空闲超时时间为 60秒 则HA 发起重连机制
timeout client 60s
#服务器端链接超时时间为 15秒 则HA 发起重连机制
timeout server 15s
#front-end IP for consumers and producters
listen rabbitmq_cluster
bind 0.0.0.0:5678
#配置TCP模式
mode tcp
#balance url_param userid
#balance url_param session_id check_post 64
#balance hdr(User-Agent)
#balance hdr(host)
#balance hdr(Host) use_domain_only
#balance rdp-cookie
#balance leastconn
#balance source //ip
#简单的轮询
balance roundrobin
#rabbitmq集群节点配置
#inter 每隔五秒对mq集群做健康检查, 2次正确证明服务器可用,2次失败证明服务器不可用,并且配置主备机制
server myrabbit1 192.168.204.128:5672 check inter 5000 rise 2 fall 2
server myrabbit2 192.168.204.128:5673 check inter 5000 rise 2 fall 2
server myrabbit3 192.168.204.128:5674 check inter 5000 rise 2 fall 2
listen stats
bind 0.0.0.0:8101
mode http
option httplog
stats enable
#设置haproxy监控地址为http://localhost:8100/rabbitmq-stats
stats uri /rabbitmq-stats
stats refresh 5s
stats auth admin:123456
listen rabbitmq_admin
bind 0.0.0.0:8001
server myrabbit1 192.168.204.128:15672 check inter 5000 rise 2 fall 2
server myrabbit2 192.168.204.128:15673 check inter 5000 rise 2 fall 2
server myrabbit3 192.168.204.128:15674 check inter 5000 rise 2 fall 2
2 登陆查看状态
- http://ip:8101/rabbitmq-stats
- 输入设置的账号密码 :admin 123456
五、突发情况模拟测试
1 准备一个生产者,不断地生产数据
- 生产者接入的端口在这里是
5678
2 随机断开其中一个节点
- 以Rabbit3演示
docker stop myrabbit3
- 查看Haproxy状态
- 发现rabbit3节点已经变为红色
- 查看MQ状态
登陆 http://ip:8001
发现rabbit3节点已经变为红色
![]()
3 查看此时的生产者情况
- 可以看到生产者并为断开,依旧继续稳定生产消息
4 重新启动Rabbit3节点
docker start myrabbit3
- 查看HaProxy状态,由黄->绿
- 5.4.2 查看MQ状态,由黄->绿