通常我们使用rabbitmq 做消息队列,若我们是 cluster模式。若我们的网络不稳定很容易造成网络分区,监测是否发生网络分区可以使用rabbitmq的ui来看,也可以用命令来检测
rabbitmqctl cluster_status
若返回值为:
[{nodes,[{disc,['rabbit@node1', 'rabbit@node2']}]},
{running_nodes,['rabbit@node2','rabbit@node1']},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]}]
则集群状态为正常,若返回值为
[{nodes, [{disc, ['rabbit@node1','rabbit@node2']}]},
{running_nodes,['rabbit@node1']},
{cluster_name,<<"rabbit@node1">>},
{partitions, [{'rabbit@node1',['rabbit@node2']}]}]
则表示rabbitmq发生网络分区了。
此时我们要手动解决网络分区。
一、最简单的是我们重启rabbitmq集群服务,这样会造成以产生的消息队列失去了消费者,即用户的一些操作可能一直处于“转圈”等待中。
二、
为了从网络分区中恢复,首先需要挑选一个信任的分区,这个分区才有决定Mnesia内容的权限,发生在其他分区的改变将不被记录到Mnesia中而直接丢弃。手动恢复网络分区有两种思路:
1.)停止其他分区中的节点,然后重新启动这些节点。最后重启信任分区中的节点,以去除告警。
2.) 关闭整个集群的节点,然后再启动每一个节点,这里需确保你启动的第一个节点在你所信任的分区之中。
停止/启动节点有两种操作方式:
1. rabbimqctl stop/ rabbitmq-server -detached
2. rabbitmqctl stop_app/ rabbitmqctl start_app
此时我们也可以利用rabbimq自己的机制来解决网络分区
RabbitMQ提供了4种处理网络分区的方式,在rabbitmq.config中配置cluster_partition_handling参数即可,分别为:
- ignore
- pause_minority
-
autoheal
下面我们来一 一 赘述:
1.ignore
默认是ignore,如果不配置rabbitmq.config或者按如下配置:[ { rabbit, [ {cluster_partition_handling, ignore} ] } ].
ignore的配置是当网络分区的时候,RabbitMQ不会自动做任何处理,即需要手动处理。
2、pause_minority
在rabbitmq.config配置文件中配置:
[
{
rabbit, [
{cluster_partition_handling, pause_minority}
]
}
].
当发生网络分区时,集群中的节点在观察到某些节点down掉时,会自动检测其自身是否处于少数派(小于或者等于集群中一般的节点数)。少数派中的节点在分区发生时会自动关闭,当分区结束时又会启动。这里的关闭是指RabbitMQ application关闭,而Erlang VM并不关闭,这个类似于执行了rabbitmqctl stop_app命令。处于关闭的节点会每秒检测一次是否可连通到剩余集群中,如果可以则启动自身的应用,相当于执行rabbitmqctl start_app命令。
需要注意的是RabbitMQ也会关闭不是严格意义上的大多数。比如在一个集群中只有两个节点的时候并不适合采用pause-minority模式,因为由于其中任何一个节点失败而发生网络分区时,两个节点都会被关闭。当网络恢复时,有可能两个节点会自动启动恢复网络分区,也有可能还是保持关闭状态。然而如果集群中的节点远大于两个时,pause_minority模式比ignore模式更加的可靠,特别是网络分区通常是由于单个节点网络故障而脱离原有分区引起的。不过也需要考虑2v2, 3v3这种情况,可能会引起所有集群节点的关闭。这种处理方式适合集群节点数大于2个且最好为奇数的情况。
3. autoheal
在autoheal模式下,当认为发生网络分区时,RabbitMQ会自动决定一个获胜的(winning)分区,然后重启不在这个分区中的节点以恢复网络分区。一个获胜的分区是指客户端连接最多的一个分区。如果产生一个平局,既有两个或者多个分区的客户端连接数一样多,那么节点数最多的一个分区就是获胜的分区。如果此时节点数也一样多,将会以一种特殊的方式来挑选获胜分区。
配置示例如下:
[
{
rabbit, [
{cluster_partition_handling, autoheal}
]
}
].
当集群发生脑裂,重启服务无法正常恢复时,需要reset节点才能正常运转
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq1
rabbitmqctl start_app
此时再看下服务应该是正常的了。
来源:51CTO
作者:shy润物无声
链接:https://blog.51cto.com/shyln/2142635