我有一棵监督树,为简单起见,假设一位主管(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
进行terminate
→restart
循环是否有意义还是Process.exit(pid, :kill)
足够? / p>
答案 0 :(得分:3)
除了工人在使用Process.exit/2
时对退出信号有发言权外,这可能与您的情况不完全相关(尽管可能会对退出信号陷阱进行必要的重新初始化,以避免重新启动工人) ,这可能是相关的。 --- 进一步的错误意见被删除 ---
更新
感谢您指出我的错误。确实,我对某些事情感到困惑。这是一个更好的选择。
方法A 。当Process.exit(W, :kill)
被呼叫时,会发生以下情况:
'EXIT'
从被解雇的工人那里发出信号restart_child/3
,它根据指定的重新启动策略进行操作非常苗条和卑鄙。
方法B 。与另一种手动方法一起会发生以下情况:
terminate_child/2
最终致电shutdown/2
shutdown/2
默认情况下会尝试正常关闭子级,从而有机会释放所有系统资源'EXIT'
信号,因此不会自动重启子级restart_child(S, w_id)
重新启动子级,重新使用其规范并规避重新启动策略为使方法A 适用,孩子们不得分配外部资源。使用one_for_one
策略,它是一个不错的捷径,在其约束范围内很有用。使用其他策略,可能会导致其他孩子的无用和/或昂贵的重新启动。当它的约束不是问题时,这种方法可能是对稳定解决方案的合理优化。
方法B 是控制单个儿童重启的更通用的方法。它确实涉及更复杂的逻辑,以交换方式提供优美的行为。它还允许在子终止和重新启动之间放置额外的逻辑。额外的好处是使用rest_for_one
或one_for_all
策略仅重新启动目标子级的准确性。我认为,对于不断发展的应用程序来说,这是一个更好的选择,因为它不受特定约束的限制,从而可以更轻松地实现更改。