[Erlang04]为何有了rpc还有net_kernel:connect/1?

问题描述:

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的原型,可是要注意本地调用和远程调用区别在于远程节点可能失效,能够加个超时:cookie

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来作什么?oop

  注意到,咱们发信息时还要指定对应的Node名字,对于调用者是很差的,(这个参数也很差找),Erlang要的效果是:把本地节点方式和远程节点编写方式统一,将其透明化。spa

由于只要知道PID就能够给它发信息这个特性,能够分2步完成。code

1. 把要用的节点手动链接起来,server

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会自动运行,而后经过 手动开启,能够传递一系列的命令和设置参数。