2012-05-17 66 views
3

我對erlang/otp世界還是一種新鮮感,所以我想這是一個非常基本的問題。不過,我想知道進行以下操作的正確方法。如何在gen_tcp上調用(和休眠):接受並同時處理系統消息?

目前,我有一個頂級主管的應用程序。後者將監督調用gen_tcp的工作人員:接受(就緒),然後爲每個接受的連接生成一個進程。注意:對於這個問題,listen()完成的地方並不重要。

我的問題是關於讓這些工作者(那些睡在gen_tcp:accept上的工作者)尊重otp設計原則的正確方式,以這種方式他們可以處理系統消息(處理關閉,跟蹤等)據我在這裏讀到:http://www.erlang.org/doc/design_principles/spec_proc.html

所以,

  • 是否有可能使用像的gen_fsm或gen_server此可用的行爲嗎?我的猜測是否定的,因爲阻止了對gen_tcp的調用:accept/1。是否仍可以通過指定接受超時來完成它?如果是這樣,我應該在哪裏接受accept()調用?
  • 或者我應該從頭開始對它進行編碼(即:不使用一個存在的行爲),就像上面鏈接中的例子一樣?在這種情況下,我想到了一個調用gen_tcp的主循環:accept/2而不是gen_tcp:accept/1(即:指定超時),然後立即編寫接收塊,以便處理系統消息。這是正確的/可接受的嗎?

感謝提前:)

回答

0

其實我已經找到了答案在另一個問題:Non-blocking TCP server using OTP principles這裏http://20bits.com/article/erlang-a-generalized-tcp-server

編輯:這是對我很有幫助,具體的答案是:https://stackoverflow.com/a/6513913/727142

+0

兩個答案都不能解決所描述的問題。兩者都使用'gen_server'來接收系統消息,但都將'accept''工作在工作進程之外。 trapexit文章使用'prim_inet:accept',這是一個內部的,未公開的API(如有更改,恕不另行通知)。 20位文章通過'proc_lib:spawn'生成一個手動接受(添加一個包裝,但不解決問題)。它們都避免了'gen_tcp:accept'的阻塞性質,但是釋放了對'accept'的控制並且需要清理(分別管理派生進程和不得不處理消息)。 – mlb

+0

它通過解釋如何編寫一個特殊的過程來解決我的問題,該過程使用接受超時並接着處理系統消息,並且不使用未記錄的功能。我並沒有問如何寫一個非阻塞的接受,而且我也沒有產生另一個接受的過程。發佈在描述特殊過程的答案中的代碼是我在我的問題中詢問的其中一種可能性 – marcelog

+0

在20bits或trapexit文章中,我沒有看到「accept」被超時使用。你能否更新你的答案,以顯示你發現的使用超時的鏈接?我會很樂意看到另一種方法,尤其是符合spec_proc的版本! – mlb

1

由於Erlang是事件驅動的,所以處理接受/ {1,2}塊的代碼是很尷尬的。

就我個人而言,我將有一位主管,其中有一位聽衆gen_server,另一位主管爲接受工作人員。 手動接受工作人員超時(gen_tcp:accept/2),有效地輪詢,(尷尬的部分),而不是接收狀態消息。

這樣,如果一名工人死亡,它會被上面的主管重新啓動。 如果偵聽器死了,它會重新啓動,但不會重新啓動依賴該偵聽器的工作樹和監控器。 當然,如果最高管理者死亡,它會重新啓動。 但是,如果您在樹上使用supervisor:terminate_child/2,則可以有效地禁用該套接字的偵聽器和所有接受器。稍後,supervisor:restart_child/2可以重新啓動整個偵聽器+接收器工作池。

如果你想要一個應用程序來管理這個,cowboy實現上述。雖然以http爲導向,但它很容易支持用於任何協議的自定義處理程序來代替。

+0

謝謝你的資源。 Ranch_acceptor(來自牛仔源)不應該在其主循環中處理系統消息,以尊重OTP原則並能夠受到監督? – marcelog

+0

@marcelog ranch_acceptor受到監督,請參閱ranch_acceptors_sup。通過模塊和管理器,處理接受器進程的系統消息。 – mlb