抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

RabbitMQ-高可用集群

搭建RabbitMQ集群

参考上一篇【RabbitMQ-普通集群】

搭建 HAProxy 负载均衡

HAProxy 是一个免费的负载均衡软件,可以运行于大部分主流的 Linux 操作系统上。

​ Haproxy 是目前比较流行的一种群集调度工具,是使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。同类群集调度工具有很多,如LVS 和 Nginx 。相比较而言,LVS 性能最好,但是搭建相对复杂,Nginx的upstream模块支持群集功能,但是对群集节点的健康检查功能不强,性能没有HAProxy 好。

​ HAProxy 提供了 L4(TCP) 和 L7(HTTP) 两种负载均衡能力,具备丰富的功能。HAProxy 的社区非常活跃,版本更新快速(最新稳定版 1.7.2 于 2017/01/13 推出)。最关键的是,HAProxy 具备媲美商用负载均衡器的性能和稳定性。它当前不仅仅是免费负载均衡软件的首选,更几乎成为了唯一选择。

因为 RabbitMQ 本身不提供负载均衡,下面我们就搭建 HAProxy,用作 RabbitMQ 集群的负载均衡。

部署HAProxy

haproxy容器部署
容器名称 管理端口
haproxy_01 4001
haproxy_02 4002
拉取docker镜像
1
docker pull haproxy
创建HAProxy配置文件

创建一个HAProxy的配置文件haproxy.cfg

1
vi /tmp/etc/haproxy/haproxy.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
global
#工作目录
chroot /usr/local/etc/haproxy
#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
log 127.0.0.1 local5 info
#守护进程运行
daemon
defaults
log global
#默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
mode http
#两次连接失败就认为是服务器不可用
retries 2
#当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
option redispatch
#当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
option abortonclose
#日志格式
option httplog
#日志中不记录负载均衡的心跳检测记录
option dontlognull
#默认的最大连接数
maxconn 4096
#连接超时(毫秒)
timeout connect 5000
#客户端超时(毫秒)
timeout client 50000
#服务器超时(毫秒)
timeout server 50000

#监控界面
listen admin_stats
#监控界面的访问的IP和端口
bind 0.0.0.0:8888
#访问协议
mode http
#URI相对地址
stats uri /dbs
#统计报告格式
stats realm Global\ statistics
#登陆帐户信息
stats auth admin:admin
#rabbitmq-web 负载
listen proxy-rabbitMQ-web
#访问的IP和端口(前面ip=0代表任何ip都可访问)
bind 0.0.0.0:5000
#网络协议
mode tcp
#负载均衡算法(轮询算法)
#轮询算法:roundrobin
#权重算法:static-rr
#最少连接算法:leastconn
#请求源IP算法:source
balance roundrobin
#日志格式
option tcplog
# 这里是容器中的IP地址,由于配置的是轮询roundrobin,weight 权重其实没有生效
server rabbitmq_01 172.18.0.2:15672 check weight 1 maxconn 2000
server rabbitmq_02 172.18.0.3:15672 check weight 1 maxconn 2000
server rabbitmq_03 172.18.0.4:15672 check weight 1 maxconn 2000
#使用keepalive检测死链
option tcpka
#rabbitmq服务 负载
listen proxy-rabbitMQ
#访问的IP和端口(前面ip=0代表任何ip都可访问)
bind 0.0.0.0:5010
#网络协议
mode tcp
#负载均衡算法(轮询算法)
#轮询算法:roundrobin
#权重算法:static-rr
#最少连接算法:leastconn
#请求源IP算法:source
balance roundrobin
#日志格式
option tcplog
# 这里是容器中的IP地址,由于配置的是轮询roundrobin,weight 权重其实没有生效
server rabbitmq_01 172.18.0.2:5672 check weight 1 maxconn 2000
server rabbitmq_02 172.18.0.3:5672 check weight 1 maxconn 2000
server rabbitmq_03 172.18.0.4:5672 check weight 1 maxconn 2000
#使用keepalive检测死链
option tcpka

将配置文件放在宿主机目录交给容器挂载

启动docker容器
1
2
3
docker run -d --network=rabbitmq_net --ip=172.18.0.5 -v /tmp/etc/haproxy:/usr/local/etc/haproxy -p 4001:8888 -p 5000:5000 -p 5010:5010  --name=haproxy_01 --privileged=true haproxy

docker run -d --network=rabbitmq_net --ip=172.18.0.6 -v /tmp/etc/haproxy:/usr/local/etc/haproxy -p 4002:8888 -p 5001:5000 -p 5011:5010 --name=haproxy_02 --privileged=true haproxy

通过浏览器就可以访问haproxy的后端管理界面了 访问:http://192.168.64.136:4001/dbs

输入配置的用户名和密码就可以看到如下界面

测试HAProxy

访问代理WEB端口

访问代理的 5000 端口刷新多次发现正常访问

http://192.168.64.136:5000/

停止主节点
1
docker stop rabbitmqCluster01

代理端口访问WEB端没有影响

springboot 连接测试

修改配置文件地址为 ha代理地址

1
2
3
4
5
6
spring:
rabbitmq:
addresses: 192.168.64.136:5010,192.168.64.136:5011
username: guest
password: guest
......

启动服务,能够正常启动

并且能够正常发送和接收消息

1
2020-10-14 14:57:08.060  INFO 14800 --- [ntContainer#0-1] c.heima.rabbitmq.consumer.QueueConsumer  : 接收到消息:messageTest

小结

​ 上述我们通过HAProxy来代理我们的RabbitMQ集群,我们解决了RabbitMQ集群节点宕机和负载均衡的问题,但是我们所有的服务都连接到了192.168.64.136机器上的HAProxy服务上了,那么如果该机器宕机,或者HAProxy服务挂了,那么整个服务就会直接瘫痪了,即存在单点故障。

​ 那么我们如何来解决HAProxy服务的单点故障问题呢?这里我们可以利用Keepalived和HAProxy来结合起来,构建一个双机热备来保证其高可用。

搭建keepalived

首先看下RabbitMQ高可用负载均衡集群长什么样子:

keepalived的实现是要在docker服务内创建,最后宿主机中也要创建实现docker内外的连接;

为什么使用keepalived

为什么要用keepalived+haproxy实现docker下的高可用负载均衡?在不同环境下有哪些方式可以实现高可用负载均衡?

​ 首先第一点,实现负载均衡并不是只有haproxy一个中间件,网上还有很多方案是用keepalived+LVS等等,所以对于docker下的高可用负载均衡不一定只有keepalived+haproxy。

为什么这里强调的是docker、keepalived?

​ 首先我们运行环境是docker,keepalived的作用是抢占虚拟ip,docker环境下,镜像内的网段外网是无法访问的,所以我们需要一个外网在宿主机上映射到docker内的ip上,keepalived一方面可以映射ip到docker服务内,二可以在docker服务内强占虚拟ip。所以在docker搭建负载均衡的多种方案中都常见会出现keepalived。

为什么要抢占虚拟ip?为什么要用keepalived呢?

​ 负载均衡中间件(haproxy,lvs)等等在实际中不可能只是单节点存在(单节点不需要keepalived),都要有冗余设计,即集群设计,和数据库集群不一样的是,docker中实现负载均衡中间件的集群是通过抢占一个ip地址实现的,有主备和主主方式,虽然方式不一样,但都有一个心跳检测的共同点,在主节点抢占虚拟ip时,主从节点上会有心跳检测线,如果发现主节点心跳检测连不上,则从节点会主动抢占ip实现数据不中断的冗余机制;

​ 总结描述:由于是在docker环境下,我们要搭建负载均衡集群需要通过keepalived抢占虚拟ip实现,而负载均衡功能需要haproxy中间件实现,所以本次我搭建的是一个在docker环境下高可用的负载均衡方案是:keepalived+haproxy。

docker安装keepalived

docker服务内创建,我们需要进入到该服务并安装keepalived

安装keepalived

进入docker-haproxy服务

1
docker exec -ti haproxy_01 /bin/bash

更新update

1
apt-get update

安装keepalived

1
apt-get install keepalived

安装ifconfig命令 安装ping

1
2
apt-get install net-tools    
apt-get install iputils-ping
创建配置文件

创建keepalived的配置文件

1
vi /tmp/etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#取名为K1,可自定义
vrrp_instance VI_1 {
#定义节点属性
state MASTER
#定义虚拟网卡
interface eth0
#定义组vriid
virtual_router_id 100
#定义权重
priority 100
#定义心跳检测时间1秒
advert_int 1
#定义组用户密码
authentication {
auth_type PASS
auth_pass 123456
}
#定义docker内ip地址,必须要在和haproxy同一个网段
virtual_ipaddress {
172.18.0.100
}
}

如果没有安装vi 可以在宿主机编辑好配置文件后复制到docker容器

1
docker cp /tmp/etc/keepalived/keepalived.conf 4954707572d4:/etc/keepalived
启动keepalived
1
service keepalived start
检查配置是否正确

在安装keepalived的docker容器检查是否绑定了eth0网卡,出现如下内容说明绑定成功

在宿主机ping该IP,如果能够ping通说明keepalived已经正常运行了

1
ping 172.18.0.100

后续操作

​ 第二个keepalived的配置文件和第一个配置文件完全一样,如果想要分配不同的权重比列,只需要更改权重参数就可以了。

宿主机中keepalived

最后,本地宿主机安装keepalived进行外网路由

安装keepalived
1
yum install -y keepalived
配置keepalived配置文件

进入宿主机/etc/keepalived目录,编辑keepalived.conf文件内容

1
vi /etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
vrrp_instance VI_1 {
state MASTER
#这里是宿主机的网卡,可以通过ip addr查看当前自己电脑上用的网卡名是哪个
interface ens33
virtual_router_id 100
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
#这里是指定的一个宿主机上的虚拟ip,一定要和宿主机网卡在同一个网段,我的宿主机网卡ip是192.168.64.136,所以指定虚拟ip是给的90
192.168.64.150
}
}

#接受监听数据来源的端口,网页入口使用(HaProxy 访问地址)
virtual_server 192.168.64.150 8888 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
#把接受到的数据转发给docker服务的网段及端口,由于是发给docker服务,所以和docker服务数据要一致
real_server 172.18.0.100 8888 {
weight 1
}
}

#接受监听数据来源的端口,(RabbitMQ WEB访问端口)
virtual_server 192.168.64.150 15672 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
#把接受到的数据转发给docker服务的网段及端口,由于是发给docker服务,所以和docker服务数据要一致
real_server 172.18.0.100 5000 {
weight 1
}
}

#接受监听数据来源的端口,(RabbitMQ 服务端口)
virtual_server 192.168.64.150 5672 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
#把接受到的数据转发给docker服务的网段及端口,由于是发给docker服务,所以和docker服务数据要一致
real_server 172.18.0.100 5010 {
weight 1
}
}

启动宿主机keepalived

配置完后,通过命令service keepalived start启动宿主机的KP,通过ip addr查看网卡中是否出现定义的150 IP地址,如果没有出现大多数是配置文件不正确。

1
service keepalived start

通过ping 150ip地址,发现能够ping通

切换到windows上,进入cmd ping宿主机150的ip地址发现能ping通,通过浏览器输入 http://192.168.64.150:8888/dbs

进入到监听页面:

防火墙配置

​ 在此如果cmd能ping通150 ip 而网页无法进入监听界面,问题出现在防火墙上,centos7默认防火墙是没有开启开启vrrp 协议,而keepalived用的是vrrp协议,所以要么让防火强开通vrrp协议

1
2
3
4
5
6
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --in-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT

firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT 0 --out-interface ens33 --destination 224.0.0.18 --protocol vrrp -j ACCEPT
firewall-cmd --reload

firewall-cmd --reload

或者直接关闭防火墙

1
systemctl stop firewalld.service

以上防火墙命令只针对于centos7的firewalld,其他防火墙或者linux版本可以自行百度让vrrp协议能够使用即能让网页进入到监听界面。

docker-compose 任务编排

编写docker-compose.yml

内容如下,注意haproxy和keepalived配置文件同上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
version: '2'   
services:
rabbitMQ01:
image: rabbitmq:management
hostname: rabbitMQ01
container_name: rabbitMQ01
extra_hosts:
- "rabbitMQ02:172.18.0.3"
- "rabbitMQ03:172.18.0.4"
networks:
rabbitmq_net:
ipv4_address: 172.18.0.2
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmqCookie
RABBITMQ_NODE_NAME: rabbit@rabbitMQ01
ports:
- "5672:5672"
- "15672:15672"
rabbitMQ02:
image: rabbitmq:management
hostname: rabbitMQ02
container_name: rabbitMQ02
extra_hosts:
- "rabbitMQ01:172.18.0.2"
- "rabbitMQ03:172.18.0.4"
networks:
rabbitmq_net:
ipv4_address: 172.18.0.3
depends_on:
- rabbitMQ01
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmqCookie
RABBITMQ_NODE_NAME: rabbit@rabbitMQ02
ports:
- "5673:5672"
- "15673:15672"
rabbitMQ03:
image: rabbitmq:management
hostname: rabbitMQ03
container_name: rabbitMQ03
extra_hosts:
- "rabbitMQ01:172.18.0.2"
- "rabbitMQ02:172.18.0.3"
networks:
rabbitmq_net:
ipv4_address: 172.18.0.4
depends_on:
- rabbitMQ01
environment:
RABBITMQ_ERLANG_COOKIE: rabbitmqCookie
RABBITMQ_NODE_NAME: rabbit@rabbitMQ03
ports:
- "5674:5672"
- "15674:15672"
haproxy_01:
image: haproxy
container_name: haproxy01
privileged: true
volumes:
- "/tmp/etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
- "/tmp/etc/keepalived/keepalived.conf:/etc/keepalived/keepalived.conf"
networks:
rabbitmq_net:
ipv4_address: 172.18.0.5
depends_on:
- rabbitMQ01
- rabbitMQ02
- rabbitMQ03
ports:
- "4001:8888"
- "5000:5000"
- "5010:5010"
haproxy_02:
image: haproxy
container_name: haproxy02
privileged: true
volumes:
- "/tmp/etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
- "/tmp/etc/keepalived/keepalived.conf:/etc/keepalived/keepalived.conf"
networks:
rabbitmq_net:
ipv4_address: 172.18.0.6
depends_on:
- rabbitMQ01
- rabbitMQ02
- rabbitMQ03
ports:
- "4002:8888"
- "5001:5000"
- "5011:5010"

networks:
rabbitmq_net:
ipam:
config:
- subnet: 172.18.0.0/16
gateway: 172.18.0.1

编写初始化脚本

1
vi init_rarabbitmq_cluster.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash


#reset first node
echo "Reset first rabbitmq node."
#docker exec rabbitMQ01 /bin/bash -c 'rabbitmqctl stop_app'
#docker exec rabbitMQ01 /bin/bash -c 'rabbitmqctl reset'
#docker exec rabbitMQ01 /bin/bash -c 'rabbitmqctl start_app'

#build cluster
echo "开始将rabbitMQ02节点加入到rabbitMQ01集群节点..."
docker exec rabbitMQ02 /bin/bash -c 'rabbitmqctl stop_app'
docker exec rabbitMQ02 /bin/bash -c 'rabbitmqctl reset'
docker exec rabbitMQ02 /bin/bash -c 'rabbitmqctl join_cluster --ram rabbit@rabbitMQ01'
docker exec rabbitMQ02 /bin/bash -c 'rabbitmqctl start_app'

echo "开始将rabbitMQ03节点加入到rabbitMQ01集群节点..."
docker exec rabbitMQ03 /bin/bash -c 'rabbitmqctl stop_app'
docker exec rabbitMQ03 /bin/bash -c 'rabbitmqctl reset'
docker exec rabbitMQ03 /bin/bash -c 'rabbitmqctl join_cluster --ram rabbit@rabbitMQ01'
docker exec rabbitMQ03 /bin/bash -c 'rabbitmqctl start_app'


#check cluster status
echo "检查rabbitMQ01集群节点状态..."
docker exec rabbitMQ01 /bin/bash -c 'rabbitmqctl cluster_status'
echo "检查rabbitMQ02集群节点状态..."
docker exec rabbitMQ02 /bin/bash -c 'rabbitmqctl cluster_status'
echo "检查rabbitMQ03集群节点状态..."
docker exec rabbitMQ03 /bin/bash -c 'rabbitmqctl cluster_status'

# haproxy 安装keepalived
echo "开始在haproxy01安装..."
docker exec haproxy01 /bin/bash -c 'apt-get -y update&&apt-get install -y keepalived net-tools iputils-ping'
echo "开始在haproxy02安装..."
docker exec haproxy02 /bin/bash -c 'apt-get -y update&&apt-get install -y keepalived net-tools iputils-ping'

# 启动 keepalived
echo "开始启动keepalived..."
docker exec haproxy01 /bin/bash -c 'service keepalived start'
docker exec haproxy02 /bin/bash -c 'service keepalived start'

配置文件配置

HAProxy配置参考上面配置

keepalived配置参考上面配置

宿主机中keepalived

参考上面配置

启动容器

1
docker-compose up -d

执行初始化脚本

1
sh init_rarabbitmq_cluster.sh

访问测试

能够访问说明高可用已经搭建成功

评论