【发布时间】:2012-10-23 08:46:41
【问题描述】:
我有一个启动多个子进程的主管进程。目前,当孩子去世时,我会使用新的 Pid 生成一个新进程。这意味着我丢失了刚刚死亡的子进程的状态信息。我希望我的客户始终使用相同的标识符与子进程进行通信。尽管子进程可能会死亡并被主管重新启动。
我正在考虑使用唯一名称注册子进程并将子状态存储在 ets 表中。问题是 - 在 Erlang 中解决此类问题的推荐方法是什么?
谢谢!
【问题讨论】:
标签: erlang
我有一个启动多个子进程的主管进程。目前,当孩子去世时,我会使用新的 Pid 生成一个新进程。这意味着我丢失了刚刚死亡的子进程的状态信息。我希望我的客户始终使用相同的标识符与子进程进行通信。尽管子进程可能会死亡并被主管重新启动。
我正在考虑使用唯一名称注册子进程并将子状态存储在 ets 表中。问题是 - 在 Erlang 中解决此类问题的推荐方法是什么?
谢谢!
【问题讨论】:
标签: erlang
在 ets 表中存储进程状态有助于在崩溃之间保持状态,我通常使用全局注册表来为进程提供持久名称。 (玩家 200 将注册为 {player, 200}。)我不建议使用本地注册表,因为它要求您使用原子,如果您有很多子进程,您可以通过动态创建它们(如 player_200、player_201 等)
不过,在 ets 表中存储子状态有其自身的风险和问题。如果一个孩子在发生错误和保存到 ets 表之间崩溃,你应该没问题。但是,如果您处理的数据导致孩子保存垃圾状态,然后在处理下一条消息时崩溃怎么办?您将重新启动该过程,从 ets 表中加载错误状态,然后再次崩溃您的下一条消息。当然有办法解决这个问题,但你应该意识到这是一种可能性并解决它。
虽然 Erlang 隐藏了将 ets 表分配给所有进程的问题,但这样做的代价是 CPU 和潜在的争用。如果您要对 ets 表进行大量更改,则需要为性能付出代价。
如果您的孩子崩溃了,您不应该为他们寻找一种方法来消除错误条件吗?我通常会将进程崩溃视为我需要解决根本原因和修复的问题。 ?
【讨论】:
使用 ETS 表可能是保持状态的方法。 Vinoski's article 讨论了如何在保留 ETS 表数据的同时重新启动崩溃的进程。
正如@user30997 指出的那样,表中的数据实际上可能是进程崩溃的原因,因此在重新启动时,您可能想要验证表(或设置进程重新启动次数的限制......)
对于将进程与 id 相关联,您应该查看 gproc,这非常适合。
【讨论】:
使用事件源,持久化所有事件,并重放以重建状态。如果您需要快速回放,请制作快照。下面的例子: https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-oslo
其实基于这个例子构建一个完整的框架就好了。
【讨论】: