2012-11-02 31 views
8

我有一個主管進程,它啓動了一些子進程。目前,當孩子死亡時,我用新的Pid產生了一個新的過程。這意味着我放棄了剛剛去世的孩子進程的狀態信息。我希望我的客戶端使用始終相同的標識符與子進程進行通信。儘管兒童流程可能會死亡並由主管重新啓動。重新啓動erlang進程並保留狀態

我在考慮註冊具有唯一名稱的子進程並在ets表中存儲子進程狀態。問題是 - 在Erlang中解決這個問題的建議方式是什麼?

謝謝!

回答

8

將進程狀態存儲在ets表中可以使您的狀態保持在崩潰之間,我通常使用全局註冊表來爲進程提供持久名稱。 (玩家200將被註冊爲{玩家,200}。)我不推薦使用本地註冊表,因爲它需要你使用原子,如果你有很多子進程,你可以匆忙地咀嚼原子的極限動態創建它們(如player_200,player_201等)

雖然在ets表中存儲子狀態有它自己的風險和問題。如果一個孩子在發生錯誤的時刻和它保存到ets表之間崩潰,你應該沒問題。但是,如果處理導致孩子保存垃圾狀態的數據,然後在處理下一條消息時崩潰呢?您將重新啓動該進程,從ets表中加載不良狀態,並再次崩潰到下一條消息。當然有辦法解決這個問題,但你應該意識到這是一種可能性並且可以解決它。

儘管Erlang隱藏了將ets表分配給所有進程的問題,但是這是以CPU和潛在爭用爲代價的。如果你對你的ets表進行了很多改變,你將會在性能上付出代價。

如果你的孩子崩潰了,難道你不應該找他們的方式去除錯誤的情況嗎?我通常會將進程崩潰視爲我需要修復的原因。 ?

+0

我使用ets表來存儲子進程狀態的最大擔憂是我可能會引入的瓶頸。有許多進程經常改變狀態,你需要他們在每次改變發生時更新擁有新狀態的ets表的進程。每當孩子死亡時,我需要以崩潰前的相同狀態重新啓動。每當子進程死亡時,它都會通過發送{'EXIT',Pid,Reason}來通知主管。如果子進程也可以發送崩潰前的狀態,我可以用相同的狀態重新啓動,並且不需要將更新發送到ets表。 – Mark

+0

我不認爲在Erlang中這是可能的,但總的來說,我想這將是一個很好的功能。就像在兒童崩潰時向主管發送進程堆棧 – Mark

+0

@Mark我在答案中引用的文章解釋了當擁有進程崩潰時,如何使用ETS表格贈送/繼承到另一個進程,聽起來像你想要的? – johlo

5

使用ETS表格可能是保持狀態的方法。 Vinoski's article討論瞭如何在保持ETS表格數據的同時重新啓動崩潰的過程。

正如@ user30997指出,該表中的數據實際上可能是進程崩潰的原因,所以在重新啓動您可能需要驗證表(或設置在多少次的進程將重新啓動的限制... )

對於關聯進程與id的你應該看看gproc這是很好的。

+0

gproc +1應該是標準的OTP – jtmoulia

相關問題