2012-09-12 88 views
2

我有一个Erlang应用程序需要一点资源,以保持在一个节点上。我正在使gen_servers从一个进程移动到另一个进程 - 这相当容易。我处于最后一个障碍:获取创建这些gen_servers的工厂进程,以在远程节点上产生它们,而不是本地进程。 start_link的默认行为显然只在本地启动,但我没有看到任何更改该选项的选项。Erlang gen_server如何在另一个节点上启动一个gen_server?

看来,我将不得不对解决方案进行创新,并希望看看有没有人有过这样的成功之道。 IOW,推荐的解决方案是什么?

编辑

我期待在由呼叫触发的调用链:

gen_server:start_link(?Module, Args, []) 

gen_server:START_LINK/3:

start_link(Mod, Args, Options) -> 
    gen:start(?MODULE, link, Mod, Args, Options). 

创:启动/ 5:

start(GenMod, LinkP, Mod, Args, Options) -> 
    do_spawn(GenMod, LinkP, Mod, Args, Options). 

创:do_spawn/5:

do_spawn(GenMod, link, Mod, Args, Options) -> 
    Time = timeout(Options), 
    proc_lib:start_link(?MODULE, init_it, 
         [GenMod, self(), self(), Mod, Args, Options], 
         Time, 
         spawn_opts(Options)); 

proc_lib:START_LINK/5:

start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) -> 
    Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)), 
    sync_wait(Pid, Timeout). 

并最终得到我们的有趣的一点。有一种符合spawn_opt/4:

spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> 
    ... 
    ... 

,还有一个实际上是对我很有用:

spawn_opt(Node, M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) -> 
    ... 
    ... 

它博格尔斯我的脑海里,这是不暴露。我意识到一个粗心的程序员可能会尝试gen_server:在erlang节点上启动一个恰好在火星上运行的进程,并阻止半小时的调用,但当然,这就是程序员的了望。我真的坚持修改OTP或编写某种临时解决方案吗?

回答

6

我们不直接在远程节点上的start_link服务器。为了获得良好的程序结构和简单性,我们在远程节点上启动一个单独的应用程序,并将远程进程的创建委托给在远程应用程序中运行的某个进程。

由于链接到一个进程主要是为了监督或监视的目的,所以我们宁愿与本地主管而不是远程进程进行链接。如果您需要任何远程过程的活跃状态,我建议erlang:monitorerlang:demonitor

典型的分布式设置:

Node1 
+---------------+       Node2 
| App1   |       +---------------+ 
| Supervisor1 | Proc Creation Request | App2   | 
|  Processes | -----------------------> | Supervisor2 | 
|  ...... |       |  | 
|  ...... |       |  | Create Children 
|  ...... |  Monitor   |  V 
|  ...... | -----------------------> |  Processes | 
+---------------+       |  ...... | 
              +---------------+