【问题标题】:Is gen_server restart strategy copy state?gen_server 重启策略是复制状态吗?
【发布时间】:2018-11-06 15:21:04
【问题描述】:

Erlang 世界不像往常一样使用 try-catch。我想知道重新启动进程与主流语言中的 try-catch 时的性能如何。

Erlang 进程有它的小栈和堆概念,实际上在 OS 堆中分配。为什么重启有效?

希望有人让我深入了解 Beam 在对进程调用重新启动操作时该怎么做。

此外,如何使用gen_server 在其进程中保持状态。 gen_server重启时会导致复制状态操作吗?

谢谢

【问题讨论】:

  • 如果一个 gen_server 崩溃并且它的主管启动了一个新的,它不会复制状态。关键是要回到“已知良好”状态。如果它复制了状态,数据可能已经进入损坏/错误状态,这就是它首先崩溃的原因。可以手动将状态复制到新的 gen_server,但您需要非常小心这样的事情。
  • 嗨,@JustinWood,我有两个问题。 1.“已知良好”状态是init函数定义的吗? 2.进入新的初始状态会像第一次创建进程一样创建进程吗?谢谢。

标签: erlang elixir beam


【解决方案1】:

我建议阅读https://ferd.ca/the-zen-of-erlang.html

这是我的理解:重启对于修复“Heisenbug”是有效的,只有在 (Erlang) 进程处于某种奇怪状态和/或试图处理“奇怪”消息时才会发生这种情况。

假设您恢复到已知的良好状态(通过重新启动),它应该正确处理所有正常消息。重新启动并不是为了“解决所有问题”,当然也不是为了配置错误或缺少互联网连接。根据这个定义,我们可以看到复制崩溃发生时的状态并尝试从中恢复是非常危险的,因为这违背了回到已知状态的全部意义。

第二点是,假设此过程仅在处理仅占所有用户实际使用的 0.001%(或任何被认为可以忽略不计的百分比)的操作时崩溃,并且它并不真正重要(例如次要 UI 细节),那么它就是完全可以让它崩溃并重新启动,并且不需要修复它。我认为它可以成为这些案例的生产力推动因素。


关于您在 OP 评论中的问题:是的,无论您的 init 回调返回什么,您都可以在那里构建整个起始状态或从其他地方获取,完全取决于用例。

【讨论】:

  • 嗨,差不多了解状态并给出更深入的见解,谢谢。只是有点奇怪,只有 0.001% 的用户实际使用,我应该设计一个数据库库保持断开连接让它崩溃还是使用 try-catch 处理异常并将 nil 返回给调用者?
  • @LoranceChen 使用“让它崩溃”并不会限制作为库设计者可以为用户提供的界面类型。例如。您仍然可以选择将其包装在 {:error, :timeout} 元组中或引发超时异常。事实上,Elixir 社区通常遵循这种习惯用法,其中库将提供同一函数的callcall! 版本,只有前者返回一个元组(从不使调用者崩溃),后者引发,所以最终用户可以选择他们想要什么样的行为。最初的评论侧重于应用程序设计的观点,但想法是一样的。
猜你喜欢
  • 2011-09-04
  • 2020-04-27
  • 1970-01-01
  • 2021-06-21
  • 2018-02-23
  • 1970-01-01
  • 2013-09-29
  • 2021-09-17
  • 2011-07-26
相关资源
最近更新 更多