记一次【RabbitMQ集群网络分区】的问题,以及网络分区时的影响范围和如何恢复
172.29.40.101(rabbitmq-1)
172.29.40.102(rabbitmq-2)
172.29.40.103(rabbitmq-3)
1)RabbitMQ 集群发生网络分区时,RabbitMQ Management UI管理平台上,overview概览页面会显示如下告警提示:

可以明确看到发生分区的节点:
The nature of the partition is as follows:
| Node | Was partitioned from |
|---|---|
| rabbit@rabbitmq-3 | rabbit@rabbitmq-1 |
2)我们可以登录到rabbit@rabbitmq-3对应的机器上,
cd /usr/local/rabbitmq_server-3.5.6/sbin
./rabbitmqctl cluster_status


集群和网络分区问题,一般指集群节点之间出现了网络故障。
RabbitMQ集群可用于实现不同的目标:通过节点间数据镜像复制以提高数据的安全性、提高客户端操作的可用性、提高整体吞吐量等。如果集群成员节点之间的网络连接发生故障,会影响客户端操作的数据一致性和可用性(CAP 定理)。由于不同的应用程序对一致性有不同的要求,并且可以不同程度地容忍不可用,因此可以使用不同的 分区处理策略。
RabbitMQ集群的一个节点,如果另一个节点在一段时间内(默认60秒)无法联络它,那么当前节点会确定与其对等的节点是否已经宕机。如果两个节点重新建立了联系,并且双方都认为对方已宕机,那么当前节点将确定为已经发生了分区。发生分区的节点服务器上,查看RabbitMQ日志:
[root@rabbitmq-3 rabbitmq]#cd /usr/local/rabbitmq_server-3.5.6/var/log/rabbitmq
[root@rabbitmq-3 rabbitmq]# tail -100f rabbit\@rabbitmq-3.log
可以看到分区的日志记录:
=ERROR REPORT==== 3-Aug-2022::18:10:31 ===
Mnesia('rabbit@rabbitmq-3'): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, 'rabbit@rabbitmq-1'}
当网络分区存在时,集群中发生网络分区的两个(或更多)节点都可以独立演化,因为此时双方都认为对方已经崩溃了。这种情况被称为脑裂。队列、绑定关系、交换机均可以单独创建或删除。
跨分区拆分的经典镜像队列最终将在分区的每一侧都有一个领导者,双方各自独立运行。但是官方有说明,经典镜像队列将在未来移除,改用仲裁队列模式。
除非配置了分区处理策略,例如pause_minority,否则即使网络连接恢复,集群的拆分也仍将继续。
我们所说的集群“网络”分区,实际上指的是在集群中没有任何节点发生任何故障的情况下,集群中的不同节点间发生了通信中断的现象。
除了网络故障,对正在运行的集群节点,挂起和恢复操作系统也可能导致分区。因为挂起的节点不会认为自己失败,甚至停止,但集群中的其他节点会认为它已经分区了。这种情况最常见原因是虚拟机被挂起导致的(例如将虚拟机从一台宿主机迁移到另一台宿主机)。
由虚拟机挂起和恢复操作引起的分区,往往是不对称的 - 挂起的节点不一定会看到其他节点已关闭,但会被集群的其他节点视为已关闭。这对pause_minority模式有特别的影响。
要从脑裂中恢复,首先需要选择一个我们最信任的分区,该分区将成为系统状态(模式、消息)使用的权限;在其他分区上发生的任何更改都将丢失。
停止其他分区中的所有节点,然后重新启动它们。当他们重新加入集群时,他们将从受信任的分区恢复状态。
最后,我们还应该重新启动受信任分区中的所有节点以清除警告。
停止整个集群并重新启动,这个操作可能更简单。注意,如果选择这样操作,请确保启动的第一个节点所在的分区是受信任的分区。
解决思路:从mq集群中选取一个主节点,然后重启从节点的mq服务。
问题解决:
lsof -nP -i:5672 |wc -l./rabbitmqctl force_boot./rabbitmqctl force_boot 命令依然停不掉服务,可以暴力停止:netstat -nplt | grep beam
kill -9 pid
./rabbitmqctl cluster_status,出现 {partitions,[]}] 字样,集群分区得到恢复。RabbitMQ 还提供了三种自动处理网络分区的方法:
默认ignore模式。
在pause-minority模式下,RabbitMQ会在其他节点宕机后,自动暂停那些被判定为少数派的集群节点(即小于或等于集群节点总数的一半)。因此,它从CAP定理中选择了分区容忍而不是可用性。这可以确保在发生网络分区时,单个分区中的最多节点将继续运行。少数节点将在分区开始时立即暂停,并在分区结束时再次开始。这种配置可以防止脑裂,因此能够自动恢复。
在pause-if-all-down模式下,RabbitMQ会自动暂停那些无法访问列表中任何节点的集群节点。换句话说,RabbitMQ必须关闭所有列出的节点才能暂停集群节点。
在autoheal模式下,如果一个分区被认为发生了,RabbitMQ会自动决定哪个分区获胜(获胜的分区是拥有最多客户端连接的分区),并重启所有不在这个分区中的节点。
我们可以在rabbitmq配置文件:rabbitmq.config 中,修改配置参数cluster_partition_handling指定使用哪种分区策略:
/usr/local/rabbitmq_server-3.5.6/etc/rabbitmq/rabbitmq.config
%% How to respond to cluster partitions.
%% See http://www.rabbitmq.com/partitions.html for further details.
%% 可选:autoheal、pause_minority、pause_if_all_down
%% {cluster_partition_handling, ignore},
如果使用pause_if_all_down模式,则需要附加参数:
例如:
cluster_partition_handling = pause_if_all_down
## Recovery strategy. Can be either 'autoheal' or 'ignore'
cluster_partition_handling.pause_if_all_down.recover = ignore
## Node names to check
cluster_partition_handling.pause_if_all_down.nodes.1 = rabbit@myhost1
cluster_partition_handling.pause_if_all_down.nodes.2 = rabbit@myhost2