重启erlang进程并保持状态

时间:2012-11-02 16:41:23

标签: erlang

我有一个主管进程,可以启动多个子进程。目前,当孩子死亡时,我会用新的Pid产生一个新的过程。这意味着我丢失了刚刚去世的子进程的状态信息。我希望我的客户端使用始终相同的标识符与子进程通信。尽管儿童过程可能会死亡并由主管重新启动。

我在考虑使用唯一名称注册子进程并在ets表中存储子状态。问题是 - 在Erlang中推荐这种问题的方法是什么?

谢谢!

3 个答案:

答案 0 :(得分:8)

在ets表中存储进程状态可以在崩溃之间保持状态,我通常使用全局注册表为进程提供持久性名称。 (玩家200将被注册为{player,200}。)我不建议使用本地注册表,因为它要求你使用原子,如果你有很多子进程,你可以匆忙地咀嚼你的原子极限动态创建它们(如player_200,player_201等)

在ets表中存储子状态有其自身的风险和问题。如果孩子在发生错误的时刻和保存到ets表之间崩溃,那么你应该没问题。但是,如果您处理导致子节点保存垃圾状态的数据,然后处理下一条消息时崩溃怎么办?您将重新启动该进程,从ets表加载错误状态,然后再次崩溃您的下一条消息。当然有办法解决这个问题,但你应该意识到这是一种可能性并且可以解决这个问题。

虽然Erlang隐藏了向所有进程分发ets表的问题,但它以CPU和潜在争用为代价。如果您对ets表进行了大量更改,那么您将在性能上付出代价。

如果您的孩子正在崩溃,那么您是否应该为他们寻找一种方法来消除错误的情况呢?我通常会将进程崩溃视为我需要根本原因并修复的东西。 ?

答案 1 :(得分:5)

使用ETS表可能是保持状态的方法。 Vinoski's article讨论了如何在保留ETS表数据的同时重新启动崩溃的进程。

由于@ user30997指出表中的数据实际上可能是进程崩溃的原因,因此在重新启动时,您可能希望验证表(或设置进程重启次数的限制...)

要将流程与ID相关联,您应该查看gproc,这对此非常有用。

答案 2 :(得分:0)

使用eventsourcing,保留所有事件,然后重播以重建状态。如果您需要快速重放,请创建快照。以下示例: https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-oslo

事实上,基于这个例子构建一个完整的框架会很不错。