Erlang EPMD

Posted erlang collect

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Erlang EPMD相关的知识,希望对你有一定的参考价值。

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
4369 with data:
name ns_1 at port
21101
name babysitter_of_ns_1 at port
21100
name ligaoren at port
51056

 

新启动一个节点之后,再看下epmd的情况:

 

[root@nimbus data2]# erl -name test@nimbus -setcookie 1234 
[root@nimbus
~]# epmd -names
epmd: up and running on port
4369 with data:
name test at port
35441
name ns_1 at port
21101
name babysitter_of_ns_1 at port
21100
name ligaoren at port
51056

Erlang EPMD

 

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进程.

 

 Erlang EPMDErlang 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 4370 inet_dist_listen_max 4375
erl
-sname node1 -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
erl
-sname node2 -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
erl
-sname node3 -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
erl
-sname node4 -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
erl
-sname node5 -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375

 

 

在启动上面节点的时候,我们显示指定了kernel的 inet_dist_listen_min inet_dist_listen_max值,也就是节点可侦听端口的最小值,最大值.上面节点启动成功之后,我们通过epmd -names查看一下端口注册情况

 

Erlang EPMD

epmd: up and running on port 4369 with data:
name node5 at port
4375
name node4 at port
4374
name node3 at port
4373
name node2 at port
4372
name node1 at port
4371
name abc at port
4370

Erlang EPMD

 

 

这时,我们尝试再创建一个节点试一下

erl -sname node6  -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375

 

失败了,错误信息节录如下:

 

Erlang EPMD

{error_logger,{{2014,7,3},{20,51,4}},"Protocol: ~tp: register/listen error: ~tp~
n",["inet_tcp",eaddrinuse]}
{error_logger,{{2014,7,3},{20,51,4}},crash_report,[[{initial_call,{net_kernel,in
it,[
'Argument__1']}},{pid,<0.20.0>},{registered_name,[]},{error_info,{exit,{erro
r,badarg},[{gen_server,init_it,
6,[{file,"gen_server.erl"},{line,320}]},{proc_lib
,init_p_do_apply,
3,[{file,"proc_lib.erl"},{line,239}]}]}},{ancestors,[net_sup,ke
rnel_sup,
<0.10.0>]},{messages,[]},{links,[<0.17.0>]},{dictionary,[{longnames,fal
se}]},{trap_exit,
true},{status,running},{heap_size,610},{stack_size,27},{reducti
ons,
1861}],[]]}

Erlang EPMD

 

 

 

注:上面参数修改如果是在代码中完成,如下

 application:set_env(kernel, inet_dist_listen_min, 9100).
application:set_env(kernel, inet_dist_listen_max,
9105).

 

  这个在 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,
6000},
{inet_dist_listen_max,
7999}
]}

 

 

LYSE里面就给出了使用配置文件的路子,只不过他是把这个配置放在专门的配置文件

http://learnyousomeerlang.com/distribunomicon

如果这两个参数调整了,最好干掉epmd,重新启动,之所以这样是因为epmd在所有节点关闭之后还会存在,所以必须重启以便新参数生效.

 

如何让epmd使用指定端口

默认情况下epmd使用的TCP端口是4369

ERL_EPMD_ADDRESS=127.0.0.1 ERL_EPMD_PORT=8384 epmd -daemon

交互模式下要链接指定的端口可以使用port选项

 epmd  -port 8384 -names

 

调试状态看细节 

如果启动epmd -d 启动调试,可以看到输出信息;下面的过程,我逐一启动了abc,xyz,test三个节点;然后关闭掉xyz,test节点,从下面的输出信息,可以看到节点注册和注销注册的情况.

 

Erlang EPMD

 
[root@Slave4
~]#
[root@Slave4
~]# epmd -d
epmd: Thu Jul
3 15:56:15 2014: epmd running - daemon = 0
epmd: Thu Jul
3 15:56:25 2014: ** got ALIVE2_REQ
epmd: Thu Jul
3 15:56:25 2014: registering 'abc:2', port 35383
epmd: Thu Jul
3 15:56:25 2014: type 77 proto 0 highvsn 5 lowvsn 5
epmd: Thu Jul
3 15:56:25 2014: ** sent ALIVE2_RESP for "abc"
epmd: Thu Jul
3 15:56:43 2014: ** got ALIVE2_REQ
epmd: Thu Jul
3 15:56:43 2014: registering 'xyz:2', port 42802
epmd: Thu Jul
3 15:56:43 2014: type 77 proto 0 highvsn 5 lowvsn 5
epmd: Thu Jul
3 15:56:43 2014: ** sent ALIVE2_RESP for "xyz"
epmd: Thu Jul
3 15:57:22 2014: ** got ALIVE2_REQ
epmd: Thu Jul
3 15:57:22 2014: node name already occupied abc
epmd: Thu Jul
3 15:57:22 2014: ** sent ALIVE2_RESP for "abc"
epmd: Thu Jul
3 15:57:22 2014: trying to unregister node with unknown file descriptor 6
epmd: Thu Jul
3 15:57:51 2014: ** got ALIVE2_REQ
epmd: Thu Jul
3 15:57:51 2014: registering 'test:1', port 32781
epmd: Thu Jul
3 15:57:51 2014: type 77 proto 0 highvsn 5 lowvsn 5
epmd: Thu Jul
3 15:57:51 2014: ** sent ALIVE2_RESP for "test"
epmd: Thu Jul
3 15:58:23 2014: ** got PORT2_REQ
epmd: Thu Jul
3 15:58:23 2014: ** sent PORT2_RESP (ok) for "test"
epmd: Thu Jul
3 16:05:26 2014: unregistering 'xyz:2', port 42802
epmd: Thu Jul
3 16:05:35 2014: unregistering 'test:1', port 32781

 

 

 

 

 

 

参考资料:

[1] http://www.erlang.org/doc/man/epmd.html

[2] https://github.com/goerlang/eclus 

[3] http://blog.yufeng.info/archives/2779


以上是关于Erlang EPMD的主要内容,如果未能解决你的问题,请参考以下文章

Erlang EPMD 使用非默认 EPMD 端口连接到其他主机

有没有办法阻止 Erlang 服务器自动启动 epmd?

在没有 epmd 的情况下启动 erlang VM

具有非默认 EPMD 端口的 Erlang 节点不再响应 ping

从二进制安装 Erlang 和 epmd 具有循环依赖关系

Erlang epmd 问题 - RabbitMQ 和 Ejabberd 在同一主机上