Supervisor.restart_child / 2或Process.exit(pid,:kill)?

时间:2018-08-02 10:48:14

标签: elixir supervisor

我有一棵监督树,为简单起见,假设一位主管(S)拥有一名采用W策略的工人(:one_for_one)。

在某些情况下,我需要重新初始化W,最简单的方法是将其崩溃。我有两个不同的选择:Process.exit/2和/或Supervisor.restart_child/2

Process.exit(W, :kill)

[{id, _, :worker, _}] = Supervisor.which_children(S)
Supervisor.terminate_child(S, w_id)
Supervisor.restart_child(S, w_id)

由于后者存在,所以我想它可能会更好地使用,但是我无法意识到使用它的好处。假设是针对策略:rest_for_one,并且有许多孩子,前者将重新启动工作人员列表的整个尾部,而后者将仅重新启动该特定工人。我找不到任何合理的文档,也没有在代码库中找到这种差异。

因此,问题将是:使用策略:one_by_one进行terminaterestart循环是否有意义还是Process.exit(pid, :kill)足够? / p>

1 个答案:

答案 0 :(得分:3)

除了工人在使用Process.exit/2时对退出信号有发言权外,这可能与您的情况不完全相关(尽管可能会对退出信号陷阱进行必要的重新初始化,以避免重新启动工人) ,这可能是相关的。 --- 进一步的错误意见被删除 ---

更新

感谢您指出我的错误。确实,我对某些事情感到困惑。这是一个更好的选择。

方法A 。当Process.exit(W, :kill)被呼叫时,会发生以下情况:

  1. 工作者进程被终止
  2. 上司receives 'EXIT'从被解雇的工人那里发出信号
  3. 主管呼叫restart_child/3,它根据指定的重新启动策略进行操作

非常苗条和卑鄙。

方法B 。与另一种手动方法一起会发生以下情况:

  1. terminate_child/2最终致电shutdown/2
  2. shutdown/2默认情况下会尝试正常关闭子级,从而有机会释放所有系统资源
  3. 如果孩子在超时后没有退出,则会被杀死
  4. 由于子级gets unlinked在被关闭之前,主管没有收到'EXIT'信号,因此不会自动重启子级
  5. 下一个调用restart_child(S, w_id)重新启动子级,重新使用其规范并规避重新启动策略

为使方法A 适用,孩子们不得分配外部资源。使用one_for_one策略,它是一个不错的捷径,在其约束范围内很有用。使用其他策略,可能会导致其他孩子的无用和/或昂贵的重新启动。当它的约束不是问题时,这种方法可能是对稳定解决方案的合理优化。

方法B 是控制单个儿童重启的更通用的方法。它确实涉及更复杂的逻辑,以交换方式提供优美的行为。它还允许在子终止和重新启动之间放置额外的逻辑。额外的好处是使用rest_for_oneone_for_all策略仅重新启动目标子级的准确性。我认为,对于不断发展的应用程序来说,这是一个更好的选择,因为它不受特定约束的限制,从而可以更轻松地实现更改。