博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Erlang 0098] net_kernel与节点互连,断开,监控
阅读量:7297 次
发布时间:2019-06-30

本文共 7466 字,大约阅读时间需要 24 分钟。

 之前记录过   , 魔鬼在于细节(Devils are in the details),这个模块还是有一些细节要注意,特别是官方文档上语焉不详的问题.先从net_kernel的几个小功能开始:

 

net_kernel小功能

 
1. 如果erlang vm启动的时候没有指定name,使用net_kernel可以在运行时指定
 
Eshell V5.9  (abort with ^G)1> net_kernel:start([test@nimbus]).{ok,<0.34.0>}(test@nimbus)2>

 

2. 判断当前是不是longname
 
(d@zen.com)3> net_kernel:longnames().true

 

3.  文档中提到 net_kernel:connect_node的返回值: returned ignored if the local node is not alive.
 
   "local node is not alive" 说的是net_kernel没有启动的情况:
Eshell V5.9  (abort with ^G)1> net_kernel:connect_node(a.zen.com).ignored2>

 

 
4. In a distributed Erlang system, it is sometimes useful to connect to a node without also connecting to all other nodes. 要实现这个,节点启动的时候添加 
-hidden  [ ]
 
5. 限定指定节点可以连通 
net_kernel:allow(Nodes)
 
 
  
下面的几个问题就稍微复杂一些了,都是一些细节的问题,平时不注意可能就成了大坑.
 
 

主动断开连接 

 
  net_kernel模块导出了一个disconnect方法用来主动断开与指定节点的连接.比如可以 [net_kernel:disconnect(X) || X <- nodes() -- [List_of_wanted_nodes]]. 这样批量断开一批连接.
 
  下面的情况是a,b,c连通,然后a节点主动断开与b的连接,可以看到节点之间的关系变成了下图的关系:
 

[root@nimbus ligaoren]# erl -setcookie abc -name a@zen.comErlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9  (abort with ^G)(a@zen.com)1> net_adm:ping(c@zen.com).pong(a@zen.com)2> net_adm:ping(b@zen.com).pong(a@zen.com)3> nodes().['c@zen.com','b@zen.com'](a@zen.com)4> net_kernel:disconnect(b@zen.com).true(a@zen.com)5> nodes().['c@zen.com'](a@zen.com)6> [root@nimbus ligaoren]# erl -setcookie abc -name b@zen.comErlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9  (abort with ^G)(b@zen.com)1> nodes().['c@zen.com'](b@zen.com)2>   [root@nimbus ligaoren]# erl -setcookie abc -name c@zen.comErlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9  (abort with ^G)(c@zen.com)1> nodes().['a@zen.com','b@zen.com'](c@zen.com)2> nodes().['a@zen.com','b@zen.com'](c@zen.com)3>

 

 不自动连接

 
 
    只要是涉及到引用另外的节点,比如rpc:call, 当前节点就会自动连接该节点,比如下面: 
 
Eshell V5.9  (abort with ^G)(b@zen.com)1> rpc:call(a@zen.com,erlang,now,[]).{
1356,605316,345986}(b@zen.com)2> nodes().['a@zen.com'](b@zen.com)3>

 

  如果要取消这个自动连接的行为可以使用dist_atuo_connect 参数,注意这里文档里面有个错误指定的参数不是
false,是nerver.dist_auto_connect这个参数只接收两个值nerver(不自动连接) 和 once (自动连接,默认值).其它的值都是无效的. 如果想要连接到别的节点,就需要主动调用net_kernel:connect_node方法.
 
 下面的测试,我们首先启动一个a@zen.com节点,erl -setcookie abc -name a@zen.com ,然后启动节点b@zen.com,注意启动参数中的dist_auto_connect选项:
 
[root@nimbus ligaoren]# erl -setcookie abc -name b@zen.com -kernel dist_auto_connect neverErlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9  (abort with ^G)(b@zen.com)1>  rpc:call(a@zen.com,erlang,now,[]).{badrpc,nodedown}(b@zen.com)2> net_kernel:connect_node(a@zen.com).true(b@zen.com)3>  rpc:call(a@zen.com,erlang,now,[]).{
1356,605925,729498}(b@zen.com)4> node().'b@zen.com'(b@zen.com)5>

 

  下面的情况是:(1) a@zen.com,c@zen.com 两个节点启动连通,(2) 然后启动b节点添加 dist_auto_connect never选项启动. (3) b@zen.com 节点主动连接节点a@zen.com 看下面的结果会发现,b@zen.com会收到一个异常消息: global: 'b@zen.com' failed to connect to 'c@zen.com' 在另外c@zen.com端也会接收类似的信息. (4)注意:b@zen.com在报了上面的错误之后,已经和c@zen.com连通了 
 
%% Node a@zen.comEshell V5.9  (abort with ^G)(a@zen.com)1> net_adm:ping(c@zen.com).pong(a@zen.com)2> nodes().['c@zen.com'](a@zen.com)3> %% Node c@zen.comEshell V5.9  (abort with ^G)(c@zen.com)1> nodes().['a@zen.com'](c@zen.com)2>=ERROR REPORT==== 27-Dec-2012::19:08:26 ===global: 'c@zen.com' failed to connect to 'b@zen.com'(c@zen.com)2> nodes().['a@zen.com','b@zen.com'](c@zen.com)3>   %% Node b@zen.comerl -setcookie abc -name b@zen.com -kernel dist_auto_connect neverEshell V5.9  (abort with ^G)(b@zen.com)1> net_adm:ping(a@zen.com).pang(b@zen.com)2> net_kernel:connect_node(a@zen.com).true(b@zen.com)3>=ERROR REPORT==== 27-Dec-2012::23:06:03 ===global: 'b@zen.com' failed to connect to 'c@zen.com'(b@zen.com)3> net_adm:ping(c@zen.com).pong(b@zen.com)4> nodes().['a@zen.com','c@zen.com'](b@zen.com)5>

 

节点状态监控

 
  下面让a@zen.com 设置 net_kernel:monitor_nodes(true),并连接到b@zen.com和c@zen.com节点;通过flush()可以看到a@zen.com接受到nodeup的消息,然后我们关闭c@zen.com,a@zen.com接收到了nodedown消息.启动c@zen.com之后,a节点重新与c的连接.
 
 
[root@nimbus ligaoren]# erl -setcookie abc -name a@zen.comEshell V5.9  (abort with ^G)(a@zen.com)1> net_kernel:monitor_nodes(true).ok(a@zen.com)2> net_kernel:connect_node(c@zen.com).true(a@zen.com)3> flush().Shell got {nodeup,'c@zen.com'}ok(a@zen.com)4> net_kernel:connect_node(b@zen.com).true(a@zen.com)5> flush().Shell got {nodeup,'b@zen.com'}ok(a@zen.com)6> flush().Shell got {nodedown,'c@zen.com'}ok(a@zen.com)7> nodes().['b@zen.com'](a@zen.com)8> flush().ok(a@zen.com)9> net_kernel:connect_node(c@zen.com).true(a@zen.com)10> flush().Shell got {nodeup,'c@zen.com'}ok(a@zen.com)11> flush().Shell got {nodedown,'c@zen.com'}ok(a@zen.com)12>    %%c@zen.com 配合重启 erl -setcookie abc -name c@zen.comEshell V5.9  (abort with ^G)(c@zen.com)1> q().ok(c@zen.com)2>erl -setcookie abc -name c@zen.comEshell V5.9  (abort with ^G)(c@zen.com)1> q().ok(c@zen.com)2>   %% b@zen.com 节点只是打酱油的  erl -setcookie abc -name b@zen.comEshell V5.9  (abort with ^G)(b@zen.com)1> nodes().['a@zen.com','c@zen.com'](b@zen.com)2> flush().ok(b@zen.com)3>

 

erlang:monitor_node 

 
   在ERTS里面还有一个erlang:monitor_node,这个方法用起来还是有点异常的:
 
  1.  节点a b c 互通, a节点执行了 erlang:monitor_node('c@zen.com',true). 监控c节点的状态
  2.  c节点关闭 a节点收到nodedown消息
  3.  c节点启动,a和c再次通过net_adm:ping连通
  4.  再次关闭c节点,a节点没有收到nodedown消息
  5.  启动c节点 ,在a节点重复执行 erlang:monitor_node('c@zen.com',true).
  6.  关闭c节点,a节点收到c的nodedown消息
   目前还不清楚这是设计如此,还是bug.请教了一下霸爷他说这里这样设计正常,还是很不太明白,琢磨中.不过看下面的测试,重新连接c@zen.com节点之后,该节点的最新信息已经更新到了sys_dist.
 
[root@nimbus ligaoren]# erl -setcookie abc -name a@zen.comErlang R15B (erts-5.9) [source] [64-bit] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.9  (abort with ^G)(a@zen.com)1>  erlang:monitor_node('c@zen.com',true).true(a@zen.com)2>  erlang:monitor_node('b@zen.com',true).true(a@zen.com)3> ets:tab2list(sys_dist).[{connection,'b@zen.com',up,<0.46.0>,undefined,             {net_address,{
{
127,0,0,1},51575},"zen.com",tcp,inet}, [],normal},{connection,'c@zen.com',up,<0.40.0>,undefined, {net_address,{
{
127,0,0,1},39308},"zen.com",tcp,inet}, [],normal}](a@zen.com)4> flush().Shell got {nodedown,'c@zen.com'}ok(a@zen.com)5> nodes().['b@zen.com'](a@zen.com)6> net_adm:ping(c@zen.com).pong(a@zen.com)7> nodes().['b@zen.com','c@zen.com'](a@zen.com)8> ets:tab2list(sys_dist).[{connection,'c@zen.com',up,<0.53.0>,undefined, {net_address,{
{
127,0,0,1},60762},"zen.com",tcp,inet}, [],normal},{connection,'b@zen.com',up,<0.46.0>,undefined, {net_address,{
{
127,0,0,1},51575},"zen.com",tcp,inet}, [],normal}](a@zen.com)9> flush().ok(a@zen.com)10> net_adm:ping(c@zen.com).pong(a@zen.com)11> ets:tab2list(sys_dist).[{connection,'c@zen.com',up,<0.60.0>,undefined, {net_address,{
{
127,0,0,1},39809},"zen.com",tcp,inet}, [],normal},{connection,'b@zen.com',up,<0.46.0>,undefined, {net_address,{
{
127,0,0,1},51575},"zen.com",tcp,inet}, [],normal}](a@zen.com)12> erlang:monitor_node('c@zen.com',true).true(a@zen.com)13> ets:tab2list(sys_dist).[{connection,'c@zen.com',up,<0.60.0>,undefined, {net_address,{
{
127,0,0,1},39809},"zen.com",tcp,inet}, [],normal},{connection,'b@zen.com',up,<0.46.0>,undefined, {net_address,{
{
127,0,0,1},51575},"zen.com",tcp,inet}, [],normal}](a@zen.com)14> flush().Shell got {nodedown,'c@zen.com'}ok(a@zen.com)15>

 

   好了,今天就到这里.
 
  最后,小图一张:
 

转载地址:http://uawnm.baihongyu.com/

你可能感兴趣的文章
Wireshark抓包工具使用教程以及常用抓包规则
查看>>
fedora16下更改网卡名字
查看>>
awk中NF,NR的含义
查看>>
Centos下Docker中运行neo4j 并配置挂载本地文件
查看>>
静态页面跳转传值小插件
查看>>
JetBrains公司的IDE使用技巧
查看>>
第三届中国云计算用户大会笔记和心得
查看>>
PHP7开启opcache打造强悍性能
查看>>
加载某个页面(A)时实现自动跳转到某个页面(B)
查看>>
Jenkins入门系列之——03PDF文档下载
查看>>
Digit Generator(生成元)
查看>>
php 入门笔记
查看>>
Python3.7安装PyQt5的方法
查看>>
Zoj 3781(构造)
查看>>
One error related to msxml4.dll (0x800C0014)
查看>>
“爆打”团队阿尔法发布 以及 第四周任务
查看>>
【堆】bzoj1293 [SCOI2009]生日礼物
查看>>
JavaScript的异步运行机制
查看>>
centos7安装HTTPS协议
查看>>
GNS3 模拟icmp端口不可达
查看>>