2012-11-14 56 views
3

現在,假設我們正在設計一個應用程序,它由2個Erlang節點組成。在節點A上,將有非常多的進程,數量級爲幾千。通過在節點B

在B節點發送消息到註冊的過程在節點B這些進程訪問的資源,可以說你必須通過執行以下功能啓動的進程:Erlang節點到節點消息傳遞吞吐量,超時和保證

 
start_server()-> 
    register(zeemq_server,spawn(?MODULE,server,[])),ok.
server()-> receive {{CallerPid, Ref}, {Module, Func, Args}} -> Result = (catch erlang:apply(Module, Func, Args)), CallerPid ! {Ref, Result}, server(); _ -> server() end.
在節點A,想要執行任何處理節點B上給定模塊中的任何功能都使用以下代碼段:
 
call(Node, Module, Func, Args)-> 
     Ref = make_ref(), 
     Me = self(), 
     {zeemq_server,Node} ! {{Me, Ref}, {Module, Func, Args}}, 
     receive 
       {Ref, Result} -> Result 
     after timer:minutes(3) -> 
      error_logger:error_report(["Call to server took so long"]), 
      {error,remote_call_failed} 
     end. 
因此,假設節點B上的進程 zeemq_server永遠不會關閉,並且節點A和B之間的網絡連接總是處於啓動狀態,請回答以下幾個問題:

QN 1:由於只有一個在節點B接收過程中,它的郵箱是最有可能是滿的,所有的時間。這是因爲,節點A上的進程數很多,並且在給定的時間間隔(例如2秒)內,每個進程至少會對Node B服務器進行一次調用。在哪些方面,接收可以在節點B上冗餘? ,例如,進程組e.t.c.並解釋(概念)如何取代上面的服務器端代碼。顯示客戶端會發生什麼變化。

的Qn2:在的情況下,只有一個接收器上的節點B,是否有消息中可允許的處理郵件箱的最大數目?如果單個進程郵件黃牛充斥着太多的消息,erlang會如何迴應?

Qn 3:在什麼情況下,使用上面顯示的概念,我可以保證發送請求的每個進程在超時發生之前儘快找到答案嗎?可以將節點B上的接收部分轉換爲並行操作嗎?像這樣:
 
start_server()-> 
    register(zeemq_server,spawn(?MODULE,server,[])),ok.
server()-> receive {{CallerPid, Ref}, {Module, Func, Args}} -> spawn(?MODULE,child,[Ref,CallerPid,{Module, Func, Args}]), server(); _ -> server() end.
child(Ref,CallerPid,{Module, Func, Args})-> Result = (catch erlang:apply(Module, Func, Args)), CallerPid ! {Ref, Result}, ok.
上面顯示的方法可能會增加在節點B上運行的進程的即時數量,並且這可能會由於內存而極大地影響服務。但是,它看起來不錯,並使 server()循環立即返回以處理下一個請求。你對這個修改有什麼看法?

最後:表明你應如何實現在節點B一個 Pool of receiver Threads,但看來是下一個 Name至於節點A,使得傳入消息進行復用接收機的線程之中和負載該組的過程中共享。保持問題的含義相同。

謝謝 Erlangers

+0

這與java有關嗎? –

+0

我的歉意@喬伊 –

+0

沒有得到太多的答案,最後做了什麼你不介意我問? –

回答

2

除了內存量之外,進程郵箱中消息的最大數量是無限的。

另外,如果你需要檢查郵箱大小,使用

erlang:process_info(self(),[message_queue_len,messages]). 

這將返回類似:

[{message_queue_len,0},{messages,[]}] 

我的建議是你先轉換您的服務器入一個gen_server 。這是你的工人。

接下來,我建議使用poolboy(https://github.com/devinus/poolboy)創建一個服務器實例池作爲poolboy工作者(他們的github中有一些示例Readme.md)。最後,我建議使用幫助器方法爲調用者創建一個模塊,該方法創建poolboy事務,並將池中的Worker arg應用於函數。下面的例子從他們的github cribbed:

squery(PoolName, Sql) -> 
    poolboy:transaction(PoolName, fun(Worker) -> 
            gen_server:call(Worker, {squery, Sql}) 
            end). 

這就是說,將Erlang RPC適合您的需要更好? Erlang RPC的詳細信息,地址爲http://www.erlang.org/doc/man/rpc.html。 Erlang RPC的好處在http://learnyousomeerlang.com/distribunomicon#rpc

+0

+1,很好的回答! –

0

IMO產卵新過程來處理每個請求可能是矯枉過正,但很難說如果不知道每個請求必須做什麼。

您可以擁有一個進程池來處理每個msg,使用循環方法來分發請求或基於請求類型ether處理它,將其發送給子進程或產生進程。您還可以通過查看其msg隊列並在超載時啓動新的子項來監視池化進程的負載。使用主管..只需在init中使用send_after即可每隔幾秒監視一次負載並相應地執行操作。如果可以的話,使用OTP,但是這是值得的。

我不會使用http進行專門的線路通信,我相信這是太多的開銷。您可以使用一個進程池來控制負載來處理它。