为什么要有一个监督树,而不是只有一个中央监督员?

问题描述

我正在学习Elixir和Erlang / OTP,并且想了解在构建高度可用的系统中使用监督树的重要性。

我可以看到主管在管理员工流程的生命周期中的重要性。但是,我仍然想知道为什么某些应用程序需要以层次结构的形式组织主管,而不是只有一个主管来管理所有工人?这种天真地被我忽略的结构有什么实际的好处?

借用Programming Elixir书中的示例,在哪种情况下,我们首选第一种结构而不是第二种结构?

1.  MainSupervisor
    ├── StashWorker
    └── SubSupervisor
        └──SequenceWorker

2.  MainSupervisor
    ├── StashWorker
    └── SequenceWorker

解决方法

您可能忽略的是著名的“让它崩溃”的哲学,它使进程崩溃并重新启动OTP中的一流公民。我们不将流程崩溃视为失败,而是将其视为机会进行正确重做而无需手动处理错误的机会。

主要原因是允许对失败后应重新启动的内容进行更精细的控制。为此,我们有strategies。或者,正如@Andree在评论中重申的那样:

通过组织层次结构中的监督,我们可以对系统中的子集发生故障时系统应如何响应进行更细粒度的控制

想象一下,一个应用程序有一个负责远程连接的进程和一堆进程,全部使用此资源。当连接过程崩溃时,无论如何,它都会由其主管重启,但其pid会发生变化。意味着依赖于此pid的所有过程也应该已经重新启动。使用:rest_for_one策略,开箱即用很容易。

该特定示例的另一种方法是在一个过程中管理连接,并在树的另一部分进行监督,并且在连接出现问题时,使用该连接手动使池管理程序崩溃,以重新初始化所有其中

甚至,我们可能希望手动崩溃处理此连接的进程以重新初始化它,而不是像编写if no_conn,do: reload_config_and_restart_connection这样的防御性代码,我们只是让它崩溃并由监视树使用新的正确配置重新初始化。 / p>

最后但并非最不重要的一点是,如果主管不捕获出口,它也将崩溃并向上传播。这样,我们可能无需重新编写代码即可重新初始化监督树的整个分支。