为 Erlang 监管者临时 children 有什么意义?

What is the point of having temporary children for Erlang supervisors?

Supervisors 用于重新启动失败的进程。临时进程是永远不应重新启动的进程。那么,为什么要为主管提供这种类型的 child 呢?主要是为了让它们可以作为 one_for_all 策略的一部分终止,还是在应用程序终止时终止?

主管只是为了重启工作而存在的观点存在几个问题。以下是其中的一些:

  • "temporary"的意思比较模糊
  • 重新启动因未知(可能受资源限制或其他外部原因)原因而在某处失败的作业和让 完成其作业 的进程过期是两种不同的做法东西。
  • 主管提供一致的接口或入口,不仅用于重新启动,还用于启动、日志记录、跟踪、崩溃清理、更高级别的状态服务(如 "less acceptable to fail")以及各种其他 OTP SASL 等工具内置的便利。

最终,所有进程都是临时的。要在 Erlang 系统中对此进行建模,您必须让主管产生并让某些作业过期。这就是为什么你可以给主管添加工作,有各种类型的主管,"how do I find process X" 的常见答案是 "ask its supervisor"(尽管 manager pattern 也很常见,并且涉及 更多主管).

您当然可以在代码中间生成一些随机的一次性进程来完成一些一次性任务(有时这是正确的做法),但现在您必须编写 crash在您的流程中处理代码,以防万一出现故障(如果您关心这份工作,那就是——如果您不关心,那您为什么要这样做?)。如果你经常这样做,你最终会编写一个非正式指定的、错误的实现,其中许多功能已经成为 OTP 以监督者的形式提供的一部分——这是 Greenspun's Tenth Rule 的 Erlang 版本.

(第十条规则一直在发生,因为虽然 语言 Erlang 非常小、简单并且不会成为黑客界许多误解的主题;OTP 和运行时环境是庞大、复杂,Erlang/OTP 的一部分是无数局外人误解的主题。)

大多数时候,为执行某些一次性工作而编写的模块都是用 start/0,N(或 do 或其他)类型的函数编写的,该函数实际上调用了一个命名主管,补充道一个临时工加入它的名单,并在监督下让它运转起来,即使它是临时的。这并非在所有情况下都应该做的事情,但这是很常见的事情——我倾向于默认这样的事情,直到我有理由不这样做。

换一种方式思考...在现实世界中,这个术语 "supervisor" 表示监督工作、任务或工人。它不如 "manager" 广泛,但比 "hiring new workers whenever one worker quits" 广泛得多——这对于人力资源部门来说甚至太狭窄了。

supervisor 的作用不仅仅是start/restart进程,还要杀死它们。

必须注意终止进程,因为在长期运行的应用程序中,存在累积 "orphan" 个无用进程的风险。因此,根据经验,每个进程都应该与其他进程链接,除非它保证在有限的时间内自行消亡。

这可以在模块本身中完成,例如,当一个进程 A 产生一个进程 B 并且它们应该总是在相同的条件下死亡时(不要忘记一个进程随着reason 'normal' 不会将其死亡传播到链接的进程)。但这有两个主要的不便之处:

  • 由于情况通常要复杂得多,它会向您的模块添加一些(很多?)进程管理代码,与主要用途代码混合,降低应用程序的可读性。
  • 它会给你一个非常局部的(本地的)流程管理视图,同时它是一个横向和架构问题。这再次导致流程管理的可读性差。

监督者的使用,实际上是监督树,允许您将流程管理与应用程序代码分开。它提供了一个全面、集中和标准化的视图,集成在 OTP 环境中。

存在临时流程(在某些情况下占多数);他们的生命周期必须得到管理;这是主管的工作。