测试环境准备: MQ服务器集群地址,版本号为3.7.8:
管理控制台地址:http://173.101.4.6:15672/#/queues
集群状态 rabbitmqctl cluster_status
集群操作相关命令:
创建一个RabbitMQ集群涉及到如下步骤:
安装RabbitMQ: 在每台要在集群中运行的机器上安装RabbitMQ。可以参考RabbitMQ官方文档
配置.erlang.cookie文件: RabbitMQ基于Erlang语言。其中.erlang.cookie文件用于在Erlang节点之间进行通信。在一个集群里,所有服务器的.erlang.cookie文件必须保持一致。这个文件通常位于用户的主目录下(/var/lib/rabbitmq)。拷贝一台机器上的.erlang.cookie文件内容到其它所有服务器上。
开始配置集群: 在一台机器上启动RabbitMQ应用,然后在所有其他机器上执行下面命令,加入到集群中(例如,你想把mq2,mq3加入到mq1的集群中):
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@mq1
rabbitmqctl start_app
验证集群配置: 使用下面的命令在每台机器上检查集群状态,保证它们都在集群中:
rabbitmqctl cluster_status
添加节点到集群: 首先,停止你想要添加到集群的节点的应用进程。你可以使用 rabbitmqctl stop_app 命令。然后,使用 rabbitmqctl join_cluster <clusternode> 命令将节点加入到集群。这里,<clusternode>应该被替换为集群中的一个运行的节点。最后,再使用 rabbitmqctl start_app 命令启动应用。
从集群中移除节点: 你需要先停止你想要移除的节点的应用进程。然后,执行 rabbitmqctl forget_cluster_node <node> 命令。这里,<node>应该被替换为你要从集群中移除的节点。即使节点已经停止运行或者从网络上移除,你仍然需要在集群中的一个运行的节点上执行此命令,来从集群元数据中删除该节点。
举例:
1. 添加节点到集群:
在新节点上执行以下命令,将其加入集群:
rabbitmqctl stop_app
rabbitmqctl reset # Be careful, this will remove all data on the node
rabbitmqctl join_cluster rabbit@mq01.omms.com
rabbitmqctl start_app
上面的命令中, rabbit@mq01.omms.com 应被替换为你的集群中任意一个运行的节点。
注意: rabbitmqctl reset 命令会清除当前节点上所有的数据和配置,执行该命令前,请确保该节点上没有需要保留的数据。
- 从集群中删除节点:
在集群中任意一个运行的节点上执行以下命令,将节点从集群中删除:
rabbitmqctl forget_cluster_node rabbit@mq02.omms.com
上面的命令中, rabbit@mq02.omms.com 应被替换为你要移除的节点。
注意: 即使你移除的节点已经停止运行或者与网络断开连接,你仍需要运行 rabbitmqctl forget_cluster_node 命令来清除集群中的元数据。
模拟集群分区(脑裂现象),命令准备
阻止mq01与其他节点通讯:
iptables -A INPUT -s 173.101.4.7 -j DROPiptables -A INPUT -s 173.101.4.8 -j DROPiptables -A OUTPUT -d 173.101.4.7 -j DROPiptables -A OUTPUT -d 173.101.4.8 -j DROP
以上命令将mq01与mq02和mq03之间的通信丢弃。此时,mq01与其他节点无法通信,从而模拟了网络分区的情况。
恢复mq01与其他节点通讯:
iptables -D INPUT -s 173.101.4.7 -j DROPiptables -D INPUT -s 173.101.4.8 -j DROPiptables -D OUTPUT -d 173.101.4.7 -j DROPiptables -D OUTPUT -d 173.101.4.8 -j DROP
以上命令解除了mq01与其他节点的通信阻止。这样,mq01就可以恢复与mq02和mq03的正常通信了。但是因为数据不同步,导致脑裂现象。
查看集群集群分区后状态
集群分区处置流程:
RabbitMQ集群分区处置模式设置:
cluster_partition_handling 这个选项有三个可能的值:ignore, autoheal, pause_minority。
ignore: 这是默认设置,意味着RabbitMQ在网络分区发生时将无视网络分区,每个分区将独立运作,分区解决后将要耗费很长时间来同步数据。
autoheal: 这个设置会在发生网络分区时,强制节点从最大的分区(copying its state)中自我恢复,这个过程称为“healing”,healing过程结束后可即刻恢复服务。(最常用的设置,通过RabbitMQ自行恢复)
pause_minority:这个设置会在网络分区发生时,检测哪个分区的节点最多,然后暂停节点较少的分区。这可能会导致RabbitMQ服务暂停,但是当分区修复后,服务可以立即恢复。
在新版本的RabbitMQ(3.7.0以上)中,推荐使用新的配置文件格式,即rabbitmq.conf。你可以按如下方式来修改cluster_partition_handling的设置:
173.101.4.6、173.101.4.7、173.101.4.8三台均配置
打开你的rabbitmq.conf文件,你可以使用以下命令:
sudo vi /etc/rabbitmq/rabbitmq.conf
在文件的末尾,添加以下内容:
cluster_partition_handling = autoheal
保存并关闭文件。
如果mq状态为暂停,则重启RabbitMQ服务,如果状态正常则无需重启:
sudo service rabbitmq-server restart
然后再依次重启,173.101.4.7和173.101.4.8。
测试结论:
- 3.7.8版本的RabbitMQ,仍然存在网络波动的状态下出现集群分区的风险。
- 经过测试环境验证。建议在MQ集群配置的时候,增加集群分区处置模式的配置,即在/etc/rabbitmq/rabbitmq.conf增加cluster_partition_handling = autoheal,如果有这个配置,网络状态恢复后,MQ分区模式会自动恢复,无需手动去恢复。如果无该配置,需要手动进行恢复。
- 应用程序端在连接MQ集群时应该设置为主动重连模式,目前在测试环境发现部分队列在集群恢复后,不能自动消费数据了。