1. 程式人生 > >[Erlang 0123] Erlang EPMD

[Erlang 0123] Erlang EPMD

 epmd程序和Erlang節點程序如影隨形,在Rabbitmq叢集,Ejabberd叢集,Couchbase叢集產品文件中都會有相當多的內容講epmd,epmd是什麼呢?   epmd 是Erlang Port Mapper Daemon的縮寫,全稱足夠明確表達它的功能了(相比之下,OTP就是一個難以從字面理解的名字);epmd完成Erlang節點和IP,埠的對映關係,比如在我的測試機上,
[[email protected] 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的情況:
[[email protected] data2]# erl -name [email protected] -setcookie 1234 
[roo[email protected] ~]# 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
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 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檢視一下埠註冊情況
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
這時,我們嘗試再建立一個節點試一下
erl -sname node6  -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
失敗了,錯誤資訊節錄如下:
{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}],[]]}
是的,啟動失敗的原因是在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裡面就給出了使用配置檔案的路子,只不過他是把這個配置放在專門的配置檔案 如果這兩個引數調整了,最好乾掉epmd,重新啟動,之所以這樣是因為epmd在所有節點關閉之後還會存在,所以必須重啟以便新引數生效.