2012-09-12 91 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 | 
+---------------+       |  ...... | 
              +---------------+