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