[Erlang04]為什麼有了rpc還有net_kernel:connect/1?

寫著寫著就懂了發表於2014-05-13

問題描述:

RPC(Remote Procedure Call)遠端程式呼叫:

如果要給另一個節點發資訊:可以簡單寫成:

call(Msg,Node) ->
   {server,Node}!{self(),Msg},
   receive
     {ok,Res} ->
         Res
end.

server() ->
 register(server,self()),
 loop().

loop() ->
   receive
       {Pid,N} ->
               Pid!{ok,N*N}
   end,
   loop().

以上就是RPC的原型,但是要注意本地呼叫和遠端呼叫區別在於遠端節點可能失效,可以加個超時:

call(Msg,Node) ->
   {server,Node}!{self(),Msg},
   receive
     {ok,Res} ->
         Res
    after 1000 ->
       {error,timeout}
end.

Tip: 但是要特別注意的是:超時後仍可能收到訊息並儲存在程式郵箱中,遠端伺服器很忙或網路不佳時,如果你不重新整理訊息,下次call/2並且傳送一個新的請求時,最終你取出了是佇列的每一個訊息,就是你call(A,Node)timeout了,又call(B,Node),可能你得到的是A的結果,這個不重新整理真悲劇。

erlang把上面的原理也用gen_server封裝了下,就有了rpc:call(Node,Module,Func,Args)這個函式。

以上來源於:Erlang程式設計指南

問題:都已經可以用RPC和遠端節點通訊了,還要net_kernel來做什麼?

  注意到,我們發資訊時還要指定對應的Node名字,對於呼叫者是不好的,(這個引數也不好找),Erlang要的效果是:把本地節點方式和遠端節點編寫方式統一,將其透明化。

因為只要知道PID就可以給它發資訊這個特性,可以分2步完成。

1. 把要用的節點手動連線起來,

2.使用加強版本的global:whereis_name/1代替erlang:whereis/1.

所以這就是net_kernel的作用:用於手動啟動,停止,連線和監控節點的構造。

這樣你發資訊可以這樣子!和本地是一樣了啦!!!

erlang:send(global:whereis_name(test),for_test).

Tips:

    1. 這裡使用:net_kernel:connect/1成功的前提一定是cookie相同;

    2. erl 可以用-connect_all_false 標記,來不讓別的節點連線,系統也不會保留連線節點的全域性表,這樣就可以阻止全域性宣告。

    3. erl –hidden將節點隱藏起來:原因如果N個節點隱藏互連,就會互相監視,要保持N*(N-1)/2的連線,增加了節點凌晨傳送監控訊息的開銷,所以就把不用的節點先隱藏,要用的時候再用net_kerlel:connect(Node)建立;

    4. erl –name –sname 最好不要混用;

    5. nep_adm: ping(Node)可以Node有沒有連線上來pong通,pang不通.

 

epmd程式:如果你是在用UDP或TCP等協議來做分散式的話:

以下摘自Erlang程式設計指南

epmd是erlang執行時系統的一部分,它為erlang分散式的節點扮演了埠對映看守程式的角色,無論多少分散式節點執行在它上面,每個機器 只會啟動一個epmd看守程式程式,監聽來自己埠4369的所有連線請求,並把綜們對映到被接節點的監聽埠,如果還沒有開始執行,當啟動你第一個分散式erlang節點時epmd會自動執行,然後通過 手動開啟,可以傳遞一系列的命令和設定引數。

相關文章