模拟RabbitMQ网络分区-阿里云开发者社区

开发者社区> 微服务> 正文

模拟RabbitMQ网络分区

简介: 1. 概述 正常情况下,很难观察到RabbitMQ网络分区的发生。为了更好的理解网络分区,需要某些手段将其模拟出来,以便对其做相应的分析处理,进而在正式应用环境中遇到类似情形可以处理的游刃有余。

1. 概述

正常情况下,很难观察到RabbitMQ网络分区的发生。为了更好的理解网络分区,需要某些手段将其模拟出来,以便对其做相应的分析处理,进而在正式应用环境中遇到类似情形可以处理的游刃有余。往长远方面讲,也可以采取一些必要的手段去避免网络分区的发生,或者可以监控网络分区以便对其迅速处理。

模拟网络分区的方式有多种,主要分为以下3大类:

  1. iptables封禁/解封IP地址或者端口号。
  2. 关闭/开启网卡。
  3. 挂起/恢复操作系统。

下面对这3大类做详细分析。

2. iptables的方式

由于RabbitMQ集群内部节点通信端口默认为25672,可以封禁这个端口来模拟出net_tick_timeout,然后再开启此端口让集群判断出网络分区的发生。举例说明,整个RabbitMQ集群由3个节点组成,分别为node1, node2, node3。此时我们要模拟node2节点被剥离出当前分区的情形,即模拟[node1, node3]和[node2]两个分区。可以在node2上执行如下命令以封禁25672端口。如果在配置中修改过这个端口号,可以将下面的命令改成相应的端口号即可。

iptables -A INPUT -p tcp --dport 25672 -j DROP
iptables -A OUTPUT -p tcp --dport 25672 -j DROP

同时需要监测各个节点的服务日志,当有如下相似信息出现时即为已经判定出net_tick_timeout:

=INFO REPORT==== 10-Oct-2017::11:53:03 ===
rabbit on node rabbit@node2 down

=INFO REPORT==== 10-Oct-2017::11:53:03 ===
node rabbit@node2 down: net_tick_timeout

当然,如果不想去监测各个节点的服务日志,也可以等待75秒以确保出现net_tick_timeout。注意此时只判定出net_tick_timeout,要等node2网络恢复之后,即解封25672端口之后才会判定出现网络分区。解封命令如下:

iptables -D INPUT 1
iptables -D OUTPUT 1

至此,node2节点与其他节点的内部通信已经恢复,如果此时查看集群的状态可以发现[node1, node3]和[node2]已形成两个独立的分区。

还可以使用iptables封禁IP地址的方法模拟网络分区。假设整个RabbitMQ集群的节点名称与其IP地址对应如下:

node1 192.168.0.2
node2 192.168.0.3
node3 192.168.0.4

如果要模拟出[node1, node3]和[node2]两个分区的情形,可以在node2节点上执行:

iptables -I INPUT -s 192.168.0.2 -j DROP
iptables -I INPUT -s 192.168.0.4-j DROP

对应的解封命令为:

iptables -D INPUT 1
iptables -D INPUT 1

或者也可以分别在node1, node3节点上执行:

iptables -I INPUT -s 192.168.0.3 -j DROP

与其对应的解封命令为:

iptables -D INPUT 1

如果集群的节点部署有跨网络分段的话,可以采取禁用整个网络段的方式模拟网络分区。假设RabbitMQ集群中3个节点和其对应的IP关系如下:

node1 192.168.0.2
node2 192.168.1.3
node3 192.168.0.4

如果要模拟出[node1, node3]和[node2]两个分区的情形,可以在node2节点上执行:

iptables -I INPUT -s 192.168.0.0/24 -j DROP

对应的解封命令也是:iptables -D INPUT 1。

3. 封禁/解封网卡的方式

操作网卡的方式和iptables的方式有相似之处,都是模拟网络故障来产生网络分区。首先需要使用ifconfig命令来查询出当前的网卡编号,如下所示,一般情况下单台机器只有一个网卡。(这里暂时不考虑多网卡的情形,因为对于RabbitMQ来说,多网卡的情况造成的网络分区异常复杂。)

[root@node1 rabbit@node1]# ifconfig
eth0      Link encap:Ethernet  HWaddr FA:16:3E:A8:FF:31  
          inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.224.0
          inet6 addr: fe80::f816:3eff:fea8:ff31/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:547632449 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5745162 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:82813557343 (77.1 GiB)  TX bytes:3099664440 (2.8 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:111152 errors:0 dropped:0 overruns:0 frame:0
          TX packets:111152 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:5401343 (5.1 MiB)  TX bytes:5401343 (5.1 MiB)

假设在node1, node2, node3三个节点的RabbitMQ集群中,node2的网卡编号为eth0,此时要模拟网络分区[node1, node3]和[node2]的情形,需要在node2上执行以下命令关闭网卡:

ifdown eth0

待判定出net_tick_timeout之后,再开启网卡:

ifup eth0

这样就可以模拟出网络分区的情形。当然也可以使用service network stop和service network start两个命令来模拟网络分区,原理同ifdown/ifup eth0的方式。

4. 挂起/恢复操作系统的方式

除了模拟网络故障的方式,操作系统的挂起和恢复操作也会导致集群内节点的网络分区。因为发生挂起的节点不会认为自身已经失败或者停止工作,但是集群内的其他节点会这么认为。如果集群中的一个节点运行在一台笔记本上,然后你合上了笔记本,那么这个节点就挂起了。或者一个更常见的现象,集群中的一个节点运行在某台虚拟机上,然后虚拟机的管理程序挂起了这个虚拟机节点,这样节点就被挂起了。待(0.75*net_ticktime, 1.25*net_ticktime)时间之后,判断出net_tick_timeout,再恢复挂起的节点即可以模拟出网络分区的情形。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
微服务
使用钉钉扫一扫加入圈子
+ 订阅

构建可靠、高效、易扩展的技术基石

其他文章