epmd进程和Erlang节点进程如影随形,在Rabbitmq集群,Ejabberd集群,Couchbase集群产品文档中都会有相当多的内容讲epmd,epmd是什么呢?
  epmd 是Erlang Port Mapper Daemon的缩写,全称足够明确表达它的功能了(相比之下,OTP就是一个难以从字面理解的名字);epmd完成Erlang节点和IP,端口的映射关系,比如在我的测试机上,
 
[root@nimbus data2]# epmd -names
epmd: up and running on port with data:
name ns_1 at port
name babysitter_of_ns_1 at port
name ligaoren at port
新启动一个节点之后,再看下epmd的情况:
 
[root@nimbus data2]# erl -name test@nimbus -setcookie
[root@nimbus ~]# epmd -names
epmd: up and running on port with data:
name test at port
name ns_1 at port
name babysitter_of_ns_1 at port
name ligaoren at port
epmd什么时候启动?
 
     文档里面说的是" if the node is to be distributed ",其实从实际操作的角度看,只要启动时候启动选项包含-name 或者-sname就会自动启动epmd;如果由于意外关闭了epmd进程,可以通过/usr/local/lib/erlang/erts-6.0/bin/epmd -daemon 启动epmd(注意版本不同路径也会不同).下面我们分别通过erl -sname tt 和 erl 启动两个节点,通过observer看下两种方式启动之后的应用程序结构,比较一下可以发现,前者多启动了net_kernel和erl_epmd进程.
 
 
 
如何让epmd只侦听指定的IP
 
要实现这个目标,有两种方式,1.使用环境变量
 
ERL_EPMD_ADDRESS=127.0.0.1 epmd -daemon
或者使用启动参数
 
epmd -address IPList 
 
或者
 
erl ... -kernel inet_dist_use_interface "{127,0,0,1}" 
 
如何指定Erlang节点互联的动态端口范围
 
  从上面的简单实验可以看到每个分布式节点启动之后,都会在epmd一个动态的端口用来节点间通信.在实际的环境中,我们不可能在防火墙里面把所有的端口都开放出来,那么怎么限制Erlang节点使用的端口范围呢?答案就是 inet_dist_listen_min inet_dist_listen_max 选项
 
erl -sname abc  -kernel inet_dist_listen_min  inet_dist_listen_max
erl -sname node1 -kernel inet_dist_listen_min inet_dist_listen_max
erl -sname node2 -kernel inet_dist_listen_min inet_dist_listen_max
erl -sname node3 -kernel inet_dist_listen_min inet_dist_listen_max
erl -sname node4 -kernel inet_dist_listen_min inet_dist_listen_max
erl -sname node5 -kernel inet_dist_listen_min inet_dist_listen_max
在启动上面节点的时候,我们显示指定了kernel的 inet_dist_listen_min inet_dist_listen_max值,也就是节点可侦听端口的最小值,最大值.上面节点启动成功之后,我们通过epmd -names查看一下端口注册情况
 
epmd: up and running on port  with data:
name node5 at port
name node4 at port
name node3 at port
name node2 at port
name node1 at port
name abc at port
这时,我们尝试再创建一个节点试一下
erl -sname node6  -kernel inet_dist_listen_min  inet_dist_listen_max 
失败了,错误信息节录如下:
 
{error_logger,{{,,},{,,}},"Protocol: ~tp: register/listen error: ~tp~
n",["inet_tcp",eaddrinuse]}
{error_logger,{{,,},{,,}},crash_report,[[{initial_call,{net_kernel,in
it,['Argument__1']}},{pid,<0.20.>},{registered_name,[]},{error_info,{exit,{erro
r,badarg},[{gen_server,init_it,,[{file,"gen_server.erl"},{line,}]},{proc_lib
,init_p_do_apply,,[{file,"proc_lib.erl"},{line,}]}]}},{ancestors,[net_sup,ke
rnel_sup,<0.10.>]},{messages,[]},{links,[<0.17.>]},{dictionary,[{longnames,fal
se}]},{trap_exit,true},{status,running},{heap_size,},{stack_size,},{reducti
ons,}],[]]}
 
是的,启动失败的原因是在epmd注册失败,没有可用的动态端口可以分配给新节点了,所以报出的是地址正在使用的错误.
 
注:上面参数修改如果是在代码中完成,如下
 application:set_env(kernel, inet_dist_listen_min, ).
application:set_env(kernel, inet_dist_listen_max, ).
  这个在 Erlang FAQ中有提到 http://www.erlang.org/faq/how_do_i.html 5.18  ...run distributed Erlang through a firewall?
 
如果是配置在Confige文件中,配置节为:
{ kernel, [
{inet_dist_listen_min, },
{inet_dist_listen_max, }
]}
 
LYSE里面就给出了使用配置文件的路子,只不过他是把这个配置放在专门的配置文件
如果这两个参数调整了,最好干掉epmd,重新启动,之所以这样是因为epmd在所有节点关闭之后还会存在,所以必须重启以便新参数生效.
 
如何让epmd使用指定端口
默认情况下epmd使用的TCP端口是4369
ERL_EPMD_ADDRESS=127.0.0.1 ERL_EPMD_PORT= epmd -daemon 
交互模式下要链接指定的端口可以使用port选项
 epmd  -port  -names

调试状态看细节

如果启动epmd -d 启动调试,可以看到输出信息;下面的过程,我逐一启动了abc,xyz,test三个节点;然后关闭掉xyz,test节点,从下面的输出信息,可以看到节点注册和注销注册的情况.
 
[root@Slave4 ~]#
[root@Slave4 ~]# epmd -d
epmd: Thu Jul :: : epmd running - daemon =
epmd: Thu Jul :: : ** got ALIVE2_REQ
epmd: Thu Jul :: : registering 'abc:2', port
epmd: Thu Jul :: : type proto highvsn lowvsn
epmd: Thu Jul :: : ** sent ALIVE2_RESP for "abc"
epmd: Thu Jul :: : ** got ALIVE2_REQ
epmd: Thu Jul :: : registering 'xyz:2', port
epmd: Thu Jul :: : type proto highvsn lowvsn
epmd: Thu Jul :: : ** sent ALIVE2_RESP for "xyz"
epmd: Thu Jul :: : ** got ALIVE2_REQ
epmd: Thu Jul :: : node name already occupied abc
epmd: Thu Jul :: : ** sent ALIVE2_RESP for "abc"
epmd: Thu Jul :: : trying to unregister node with unknown file descriptor
epmd: Thu Jul :: : ** got ALIVE2_REQ
epmd: Thu Jul :: : registering 'test:1', port
epmd: Thu Jul :: : type proto highvsn lowvsn
epmd: Thu Jul :: : ** sent ALIVE2_RESP for "test"
epmd: Thu Jul :: : ** got PORT2_REQ
epmd: Thu Jul :: : ** sent PORT2_RESP (ok) for "test"
epmd: Thu Jul :: : unregistering 'xyz:2', port
epmd: Thu Jul :: : unregistering 'test:1', port
 是不是比较迷惑里面的ALIVE2_REQ之类的是什么意思?这就要认真对照Erlang Distribution Protocol了,对照下面的图,如果有兴趣可以研究下协议,地址: http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html  
 
 
 
最后,这里有一个Golang的项目 Eclus-EPMD replacement in Go 有兴趣的可以看下,项目地址: https://github.com/goerlang/eclus  
 
参考资料:
 
 

[Erlang 0123] Erlang EPMD的更多相关文章

  1. Erlang 103 Erlang分布式编程

    Outline 笔记系列 Erlang环境和顺序编程Erlang并发编程Erlang分布式编程YawsErlang/OTP 日期              变更说明 2014-11-23 A Outl ...

  2. [Erlang 0129] Erlang 杂记 VI

    把之前阅读资料的时候记下的东西,整理了一下. Adding special-purpose processor support to the Erlang VM   P23 简单介绍了Erlang C ...

  3. [Erlang 0124] Erlang Unicode 两三事 - 补遗

    最近看了Erlang User Conference 2013上patrik分享的BRING UNICODE TO ERLANG!视频,这个分享很好的梳理了Erlang Unicode相关的问题,基本 ...

  4. [Erlang 0122] Erlang Resources 2014年1月~6月资讯合集

    虽然忙,有些事还是要抽时间做; Erlang Resources 小站 2014年1月~6月资讯合集,方便检索.      小站地址: http://site.douban.com/204209/   ...

  5. [Erlang 0105] Erlang Resources 小站 2013年1月~6月资讯合集

    很多事情要做,一件一件来; Erlang Resources 小站 2013年1月~6月资讯合集,方便检索.      小站地址: http://site.douban.com/204209/     ...

  6. [Erlang 0057] Erlang 排错利器: Erlang Crash Dump Viewer

    http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html Erlang Crash Dump Viewer真的是排错的天兵神器,还记得我 ...

  7. [Erlang 0119] Erlang OTP 源码阅读指引

      上周Erlang讨论群里面提到lists的++实现,争论大多基于猜测,其实打开代码看一下就都明了.贴出代码截图后有同学问这代码是哪里找的?   "代码去哪里找?",关于Erla ...

  8. [Erlang 0118] Erlang 杂记 V

       我在知乎回答问题不多,这个问题: "对你职业生涯帮助最大的习惯是什么?它是如何帮助你的?",我还是主动回答了一下.    做笔记 一开始笔记软件做的不好的时候就发邮件给自己, ...

  9. [Erlang 0114] Erlang Resources 小站 2013年7月~12月资讯合集

    Erlang Resources 小站 2013年7月~12月资讯合集,方便检索.     附 2013上半年盘点: Erlang Resources 小站 2013年1月~6月资讯合集    小站地 ...

随机推荐

  1. 检验你的前端基础——Sit the test

    前端小学生向大家推荐一个网站:Sit the test.如果你是一名前端工程师或者立志于此,不妨试试此网站上面的测验题. 发现 十几天前,我在奇舞周刊的一篇文章中,发现了一个国外的技能测试网站:Sit ...

  2. DOM对象模型接口规范中的四个基本接口

    DOM对象模型的四个基本接口 在DOM对象模型接口规范中,有四个基本的接口:Document,Node,NodeList以及NamedNodeMap.在这四个基本接口中,Document接口是对文档进 ...

  3. 基于HTTP的断点传输

    最近项目需要做一个类似于迅雷的文件下载功能,这类需求可能比较常见,希望可以帮助到有需要的同学 要求: 1.支持断点传输 2. 多文件同时下载 3. 由于是客户内部试用,服务器只支持HTTP文件下载不支 ...

  4. js自动提示查询添加功能(不是自动补全)

    在工作中遇到查询某些数据,并添加到一个列表里的时候,写了一个小功能. 优点: 1.纯手工JS代码,不需要任何js框架,复制下来就能测试,无毒副作用. 2.通过模糊查询快速定位数据,并添加到列表里. 缺 ...

  5. Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值

    Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值,去属性表中设置这时候会提示你去属性表中更改返回类型. 其实存储过程返回的也是一张表,只不过有时候存储过程有点复杂或者写法不规范的话不能 ...

  6. 计算机程序的思维逻辑 (51) - 剖析EnumSet

    上节介绍了EnumMap,本节介绍同样针对枚举类型的Set接口的实现类EnumSet.与EnumMap类似,之所以会有一个专门的针对枚举类型的实现类,主要是因为它可以非常高效的实现Set接口. 之前介 ...

  7. 完整记录一则Oracle 11.2.0.4单实例打PSU补丁的过程

    本文记录了打PSU的全过程,意在体会数据库打PSU补丁的整个过程. 1.OPatch替换为最新版本2.数据库软件应用19121551补丁程序3.数据库应用补丁4.验证PSU补丁是否应用成功 1.OPa ...

  8. java中异常抛出后代码还会继续执行吗

    今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element){ i ...

  9. 严重: Exception sending context initialized event to listener instance of class

    问题描述:Exception sending context initialized event to listener instance of class org.springframework.w ...

  10. C标准头文件<ctype.h>

    主要包括了一些字符识别和转换函数 字符判断 isalnum() //函数原型 #include<ctype.h> int isalum(int c); 功能:如果输入的字符是字母(alph ...