通常状况下,若是只是为了探究 RabbitMQ 或者验证业务工程的正确性那么在本地环境或者测试环境上使用其单实例部署就能够了,可是出于 MQ 中间件自己的可靠性、并发性、吞吐量和消息堆积能力等问题的考虑,在生产环境上通常都会考虑使用 RabbitMQ 的集群方案。node
本文档旨在介绍 RabbitMQ 集群的工做原理以及在 CentOS 7 系统上安装配置具有高可用性和具有必定负载能力的 RabbitMQ 集群。linux
RabbitMQ 这款消息队列中间件产品自己是基于 Erlang 编写,Erlang 语言天生具有分布式特性(经过同步 Erlang 集群各节点的 magic cookie 来实现)。所以,RabbitMQ 自然支持 Clustering。这使得 RabbitMQ 自己不须要像ActiveMQ、Kafka 那样经过 ZooKeeper 分别来实现 HA 方案和保存集群的元数据。集群是保证可靠性的一种方式,同时能够经过水平扩展以达到增长消息吞吐量能力的目的。git
RabbitMQ 集群有两种模式:github
RabbitMQ 集群主机环境以下:bash
mq-node1(master) 10.200.100.231 master.yeaheo.com mq-node2(node01) 10.200.100.231 node01.yeaheo.com mq-node3(node02) 10.200.100.231 node02.yeaheo.com
各主机系统环境及 MQ 版本以下:cookie
$ cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) $ uname -r 3.10.0-862.el7.x86_64 Erlang : 21.1 RabbitMQ: v3.7.9
修改各主机 hosts
文件以下:网络
.... 10.200.100.231 master master.yeaheo.com 10.200.100.217 node01 node01.yeaheo.com 10.200.100.218 node02 node02.yeaheo.com ....
配置 RabbitMQ 集群首先须要在各个主机上安装并配置 Erlang 和 RabbitMQ ,Erlang安装过程能够参考: rabbitmq-erlang-installation.md RabbitMQ 具体过程能够参考:rabbitmq-single-installation.md并发
当 Erlang 和 RabbitMQ 安装完成后就能够配置 RabbitMQ 集群了。app
本次部署集群时都是将其余两个 RabbitMQ 加入到 master 主机现有集群中。socket
rabbitmq-server 启动时,会一块儿启动节点和应用,它预先设置 RabbitMQ 应用为 standalone 模式。要将一个节点加入到现有的集群中,你须要中止这个应用,并将节点设置为原始状态。若是使用 rabbitmqctl stop
,应用和节点都将被关闭。因此使用 rabbitmqctl stop_app
仅仅关闭应用
RabbitMQ 利用 erlang 的分布式特性组建集群,erlang 集群经过 magic cookie 实现,此 cookie 保存在$home/.erlang.cookie
,这里即:/var/lib/rabbitmq/.erlang.cookie
,须要保证集群各节点的此 cookie 一致,能够选取一个节点的 cookie,采用 scp 同步到其余节点:
$ scp /var/lib/rabbitmq/.erlang.cookie root@node01:/var/lib/rabbitmq/.erlang.cookie $ scp /var/lib/rabbitmq/.erlang.cookie root@node02:/var/lib/rabbitmq/.erlang.cookie
更换 cookie 后须要重启 RabbitMQ 服务:
$ systemctl stop rabbitmq-server.service $ systemctl start rabbitmq-server.service
全部节点须要使用 -detached
参数启动服务:
# 须要在全部节点上执行 $ rabbitmqctl stop $ rabbitmq-server -detached
由于将其余两个 RabbitMQ 加入到 master 主机现有集群中,因此只须要在 node01
和 node02
上操做便可:
node01 主机(10.200.100.217)上操做:
node01$ rabbitmqctl stop_app node01$ rabbitmqctl join_cluster rabbit@master ####这里集群的名字必定不要写错了 node01$ rabbitmqctl start_app
集群名字通常能够在
master
主机的日志文件中看到,须要注意的是这个集群名字须要和日志文件中保持一致,不然加入集群时会报错
node02 主机(10.200.100.218)上操做:
node02$ rabbitmqctl stop_app node02$ rabbitmqctl join_cluster rabbit@master ####这里集群的名字必定不要写错了 node02$ rabbitmqctl start_app
查看集群状态:
$ rabbitmqctl cluster_status Cluster status of node rabbit@master ... [{nodes,[{disc,[rabbit@master,rabbit@node01]},{ram,[rabbit@node02]}]}, {running_nodes,[rabbit@node02,rabbit@node01,rabbit@master]}, {cluster_name,<<"rabbit@master">>}, {partitions,[]}, {alarms,[{rabbit@node02,[]},{rabbit@node01,[]},{rabbit@master,[]}]}]
此时 node01
与 node02
也会自动创建链接,集群配置完成。
若是要使用内存节点,则可使用
rabbitmqctl join_cluster --ram rabbit@master
加入集群。
RabbitMQ 节点分为内存节点和磁盘节点:
1)内存节点(RAM):内存节点将全部的队列、交换机、绑定、用户、权限和vhost的元数据定义存储在内存中
2)磁盘节点(Disk):将元数据存储在磁盘中,单节点系统只容许磁盘类型的节点,防止重启RabbitMQ的时候,丢失系统的配置信息。
若是须要切换节点类型,能够参考以下命令:
#若是节点已经是"disk"节点,能够修改成内存节点 $ rabbitmqctl stop_app $ rabbitmqctl change_cluster_node_type ram $ rabbitmqctl start_app
1)RabbitMQ要求在集群中至少有一个磁盘节点,全部其余节点能够是内存节点,当节点加入或者离开集群时,必需要将该变动通知到至少一个磁盘节点。若是集群中惟一的一个磁盘节点崩溃的话,集群仍然能够保持运行,可是没法进行其余操做(增删改查),直到节点恢复, 或者能够设置两个磁盘节点,以保持有一个是可用的。
2)内存节点虽然不写入磁盘,可是它执行比磁盘节点要好。
3)若是集群中只有内存节点,那么不能中止它们,不然全部的状态,消息等都会丢失。
通过上述配置,集群虽然搭建成功,但只是默认的普通集群,exchange,binding 等数据能够复制到集群各节点。
但对于队列来讲,各节点只有相同的元数据,即队列结构,但队列实体只存在于建立改队列的节点,即队列内容不会复制(从其他节点读取,能够创建临时的通讯传输)。这样此节点宕机后,其他节点没法从宕机节点获取还未消费的消息实体。若是作了持久化,则须要等待宕机节点恢复,期间其他节点不能建立宕机节点已建立过的持久化队列;若是未作持久化,则消息丢失。
下边来配置策略,策略名称为 ha-all,通配符 ^ 表示匹配到的全部队列,复制到全部节点,在任一节点上执行:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
也能够复制匹配到的队列到集群中的任意两个或多个节点,而不是到全部节点,并进行自动同步:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
或者复制匹配到的队列到集群中的指定节点:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"nodes","ha-params":["rabbit@node01","rabbit@node02"]}'
至此,镜像队列策略配置完成,同时也实现了 HA。
咱们在10.200.100.218
主机上直接用 yum 安装 HAProxy 便可:
$ yum -y install haproxy
修改 HAProxy 配置文件 /etc/haproxy/haproxy.cfg
以下:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode tcp log global option tcplog option dontlognull retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen rabbitmq_cluster 0.0.0.0:5670 mode tcp balance roundrobin server node1 10.200.100.217:5672 check inter 2000 rise 2 fall 3 server node2 10.200.100.218:5672 check inter 2000 rise 2 fall 3 server node3 10.200.100.231:5672 check inter 2000 rise 2 fall 3 listen monitor 0.0.0.0:8100 mode http option httplog stats enable stats uri /stats stats refresh 5s
重启 HAProxy:
$ systemctl restart haproxy.service
以后就能够经过 http://10.200.100.218:8100/stats
查看 HAProxy 的状态了。
若是用的是云主机,能够利用云服务商本身的 LB,不必定要用 HAProxy