[Erlang14]怎样模拟节点互连后的各种失败情况?
情景:
当节点群互连时,会通过心跳包检查所连接节点是不是连接正常,这个心跳时间默认为60s,可以通过
net_kernel:set_net_ticktime(600).
来重设这个时间值,怎么测试?
每次我把其中一个节点kill掉后,与之想连的节点就会立即收到nodedown消息,根本无法测试这个ticktime是不是生效。
原因:
在Erl Doc里面关于节点互连时有一个关于节点间心跳检查的片段:
http://www.erlang.org/doc/man/kernel_app.html
net_ticktime = TickTime
Specifies the net_kernel tick time. TickTime is given in seconds. Once every TickTime/4 second, all connected nodes are ticked (if anything else has been written to a node) and if nothing has been received from another node within the last four (4) tick times that node is considered to be down. This ensures that nodes which are not responding, for reasons such as hardware errors, are considered to be down.
The time T, in which a node that is not responding is detected, is calculated as: MinT < T < MaxT where:
MinT = TickTime - TickTime / 4
MaxT = TickTime + TickTime / 4
TickTime is by default 60 (seconds). Thus, 45 < T < 75 seconds.
Note: All communicating nodes should have the same TickTime value specified.
Note: Normally, a terminating node is detected immediately.
从文档中可以看出,节点会在每TickTime/4 秒检查一下连接的节点是不是正常,如果连续4次没有收到(TickTime时间内)没有收到心跳消息,就会认为这个节点挂了,
可是如果节点是被终结掉(terminating node),其它节点会马上收到down通知.
为了测试这个心跳时间,必须要对Erlang节点互连的基本epmd和net_kernel的工作原理有所了解【Google真是万能!】。
Erlang节点使用TCP连接通讯,当开启一个新节点,它会随机选择一个端口(大约在52300左右),在EPMD(Erlang Port Mapper Daemo)注册,EPMD默认使用4369端口对外连接,

结论:
1. epmd就是Erlang里的port mapper,每台计算机上启动一个该进程,它记录/交换集群上的每个进程的端口信息:
2. 每个节点起动时会向本地的EPMD注册一个可用端口,用于收信息;
3. 当A节点尝试与B节点建立双向通信时,首先向本地的EPMD进程查询B节点信息(第一次连接当然找不到啦);
4. 找不到就会向B节点的EPMD查询B节点上可收消息的PortB,同时把A节点上的PortA携带给B节点;
5. A节点随机一个可用端口PortA1---->PortB; B节点随机一个PortB1----->PortA;
6.双向通信连接建立成功。
The following figure shows three nodes N1, N2, and N3 with their incoming connection TCP port 52383, 52236, 52275. Communication is ongoing between N1 and N2, N1 and N2 where the nodes have picked random ports R1, R2, R3, and R4.
那我们来看看3个节点相连是什么情况?

节点N1,N2,N3,分别注册52383, 52236, 52275用来建立接收的TCP连接,R1,R2,R3,R4就是随机生成的端口用来发送的TCP连接。
Erlang有很多方法来检测节点是不是可连接,比如我们上面说的节点启动时自动设置的心跳Net-Ticks(双向就用Links,单向监测就用Monitors),
1> net_kernel:monitor_nodes(true, [{node_type, visible}, nodedown_reason]).
可能失败的原因:
%%connection_setup_failed
%%no_network
%%net_kernel_terminated
%%shutdown
%%connection_closed
%%disconnect
%%net_tick_timeout
%%send_net_tick_fail
%%edget_status_failed
接下来的好戏:怎么制造出这些错误?
1 没有效果的方式:
1.1. 改变节点cookie.
众所周知:2个节点要连接在一起,必须要知道对方的cookie,那么,我们在连接已建立后,手动把cookie改一下:
1> erlang:set_cookie(node(), zhongwencool).
结果非常有趣:居然对运行中已连接的节点没有任何影响.
1.2.阻塞或杀死EPMD进程.
结果和1一样,对已连接的节点没有任何影响,这个是因为EPMD只用于连接建立之前,建立完成后就没EPMD的事啦.
2. 破坏性的方式:
2.1 使VM Crash掉:
直接在操作系统里面用
$ kill - $PID
或者使用:
1> os:cmd("kill -9 " ++ os:getpid()).
结果是对方节点马上收到了
{connection_closed}
1> erlang:halt().
或者更常见的:
1> init:stop().
但是两者了结果都是:马上收到:
{connection_closed}
3. 临时性的方式:
3.1 可以在终端使用C-z,或:
1> os:cmd("kill -STOP " ++ os:getpid()).
使VM机器Halt住。
终于我们在60s后收到了:
{net_tick_timeout}
终于看到了一个我们想要的结果,但是好像这个节点也无法再继续用了……
3.2 把 net_kernel进程给kill掉:
1> timer:kill_after(0, whereis(net_kernel)).
结果还是马上收到:
{connection_closed}
4. 阻塞端口:
使用防火墙规则阻塞端口:
$ erl -name 'n1@127.0.1.1'
$ erl -name 'n2@127.0.1.2'
这下上面的2个节点都使用不用的network interface
$ sudo iptables -I INPUT --destination 127.0.1.1 -j DROP
$ sudo iptables -I INPUT --source 127.0.1.1 -j DROP $ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 127.0.1.1/ -j DROP
-A INPUT -d 127.0.1.1/ -j DROP :
: $ sudo iptables -F
结果还是60s后收到一个:
{net_tick_timeout}
最终结果:
如果想测试nodedown消息,最好使用防火墙设置端口来模拟。
参考阅读:
1. http://blog.yufeng.info/archives/2779
2. http://www.cnblogs.com/me-sa/p/erlang-epmd.html

心中一万匹马在奔腾啊……………………………….
[Erlang14]怎样模拟节点互连后的各种失败情况?的更多相关文章
- Consul的一个更新:服务端节点故障后重连
研究了一段时间Consul,想写个攻略来着,但太赖了而且表达能力非正常人...今天发现HashiCorp果然接纳大众意见改了点东西.. 场景是: 假如Consul集群内有三个Server Node 时 ...
- 探索javascript----获得节点计算后样式
节点计算后样式是一个属性与属性值的值对对象: IE: node.currentStyle; 非IE: window.getComputedStyle(node,null); 兼容方式: func ...
- rac 11g_第二个节点重启后无法启动实例:磁盘组dismount问题
原创作品,出自 "深蓝的blog" 博客,欢迎转载,转载时请务必注明以下出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...
- es故障节点恢复后加入集群导致删除索引重新出现
es的每个shard下的文件都可以看做一个完整的lucene文件,shard数据目录下的segment文件包含了索引的分片数量,副本数量.es shard可以恢复,就是因为每个shard都包含了一份数 ...
- C#TreeView节点选中后失去焦点时改变节点背景色
C#TreeView节点选中后失去焦点时改变节点背景色 在使用TreeView控件时候,单击一个节点,当鼠标聚焦到别的地方的时候,之前点击的这个节点就看不清楚了 举例截图 单击后 ...
- 【mysql】mysql增加version字段实现乐观锁,实现高并发下的订单库存的并发控制,通过开启多线程同时处理模拟多个请求同时到达的情况 + 同一事务中使用多个乐观锁的情况处理
mysql增加version字段实现乐观锁,实现高并发下的订单库存的并发控制,通过开启多线程同时处理模拟多个请求同时到达的情况 ==================================== ...
- 【BUG】插入或者更新超过限制后写入数据库失败
Error Code: 1064 - You have an error in your SQL syntax; check the manual that corresponds to your ...
- 如何处理导出的csv无法查看身份证后三位的情况?
如何处理导出的csv无法查看身份证后三位的情况? 原因:excel中如果是常规格式无法显示那么多位数,改成文本格式就可以. 简单步骤,导入数据------>选择数据来源------>选择编 ...
- Netty:Channel 建立后消息发送失败
1. 问题现象 Channel 建立后消息发送失败: ChannelFuture future = DeviceManager.getBootstrap().connect(); deviceChan ...
随机推荐
- [Z]LaTeX入门教程
LaTeX入门教程 Contents TEX/LATEX是什么? 为什么要用TEX/LATEX? 安装 开始使用 数学符号使用中文文章的各个部分表格 行内公式与行间公式 上标与下标 常见的数学公式 行 ...
- Android基础之布局ConstraintLayout
Google I/O 2016 上发布了 ConstraintLayout,据说很强大,那就一探究竟吧! gradle配置 compile 'com.android.support.constrain ...
- Spring Test 整合 JUnit 4 使用总结
转自:https://blog.csdn.net/hgffhh/article/details/83712924 这两天做Web开发,发现通过spring进行对象管理之后,做测试变得复杂了.因为所有的 ...
- sortingOrder,sortingLayer
sortingOrder 是sortingLayer内的分级 sortingLayer是抽象的分层,用于决定2D物体绘制的先后顺序. 2D物体分两类:sprite和UI. sprite虽是2D,却可以 ...
- redis centos7
官网下载tar包 make 修改conf 修改 启动脚本 utils/redis_init_script 开放端口6379
- java算法 第七届 蓝桥杯B组(题+答案) 9.取球博弈
9.取球博弈 (程序设计) 两个人玩取球的游戏.一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目.如果无法继续取球,则游戏结束.此时,持有奇数个球的一方获胜.如果两人都是 ...
- python的 pep8 规范(看完你会感谢我的!!!)
1 缩进与换行 每级缩进使用四个空格 2 限制每行的最大长度为79个字符 3 空行 顶层函数和类之间使用两个空行 类的方法之间用一个空行 在函数中使用空行表示不同逻辑段落 4 导入位于文件的顶部 5 ...
- Unix进程特性
本篇文章主要总结分享记录一下运维工作中经常打交道的Unix进程.程序是代码的集合,而进程是运行中的程序产生的.那么进程都有那些特性呢?且看下文,部分经典且难懂的地方,使用python代码实现,可以让读 ...
- jQuery中deferred对象的使用(一)
在jquery1.5之后的版本中,加入了一个deferred对象,也就是延迟对象,用来处理未来某一时间点发生的回调函数.同时,还改写了ajax方法,现在的ajax方法返回的是一个deferred对象. ...
- 阿里云WindowsServer2012安装IIS失败
本文地址:http://www.cnblogs.com/drfxiaoliuzi/p/6388417.html 首先,向微软官方论坛的大神致敬: https://social.technet.micr ...