2

我写了一个名为director的新库。
这是一个主管图书馆。
它的一个特点是给director带来了arity 2的乐趣,director会在每次进程崩溃时调用函数,第一个参数是崩溃原因,第二个是崩溃计数,例如:

-module(director_test).
-behaviour(director).
-export([start_link/0, init/1]).

start_link() ->
    director:start_link(?MODULE, []).

init([]) ->
    ChildSpec = #{id => foo,
                  start => {m, f, args},
                  plan => [fun my_plan/2],
                  count => infinity},
    {ok, [ChildSpec]}.

my_plan(normal, Count) when Count rem 10 == 0 ->
    %% If process crashed with reason normal after every 10 times
    %%, director will restart it after spending 3000 milliseconds.
    {restart, 3000};
my_plan(normal, _Count) ->
    %% If process crashed with reason normal director will restart its
    restart;
my_plan(killed, _Count) ->
    %% If process was killed, Director will delete it from its children
    delete;
my_plan(Reason, Count) ->
    %% For other reasons, director will crash with reason {foo_crashed, Reason}
    {stop, {foo_crashed, Reason}}.

我在 Slack 中宣布了我的库,他们想知道以这种方式编写新主管!有人说“我倾向于不让主管处理退避”。
最后他们没有告诉我干净的信息,我认为我需要更多地了解主管及其职责等。我认为主管是一个应该了解何时重新启动哪个孩子以及何时删除哪个孩子以及何时不重新启动的过程重启哪个孩子。我对吗?

你能告诉我一些我在 Director 中没有的 OTP/Supervisor 的好功能吗?(导演特征列表

4

2 回答 2

2

你把监督管理的想法混在一起了。

监督已经是 OTP 的一部分。基本思想是:

  • 任何进程都不可能成为孤儿
  • 崩溃将重新启动或中止,这是在编写内部逻辑之前做出的架构决策。
  • 崩溃可以在外部记录(由任何失败的进程处理)。
  • 错误处理代码、崩溃取证等永远不会作为监督的一部分发生。曾经。(复杂的逻辑导致复杂的怪异,监督需要简单、健壮和可靠。)

管理是您的系统中可能存在也可能不存在的东西,因此由您决定。您的想法是,您将拥有一个(通常命名的)流程来指导您的(受监督的)员工正在执行的整体高级任务。拥有一个管理器流程可以让您对正在完成的整体工作进行单点控制——这也意味着它是一个单一的地方,您可以告诉您开始、停止、暂停自身等整体工作,这是您可以添加的地方关于基于某些崩溃条件的选择性重启的附加逻辑。

将“监督”视为一种低级的、系统框架类型的想法。它在所有程序中总是相同的,就像打开文件或处理网络套接字一样。将管理视为您的程序完成其工作所需解决的实际问题的一个独立部分。

管理可能复杂也可能不复杂。监督必须始终统一和简单。赋予监督者过多的责任会使他们难以理解和调试,并且经常导致业务问题——监督者超载可能是系统中的主要问题。不要让您的主管承担高级别的管理任务。

不久前,我在 Erlang 中写了一篇关于“服务 -> 工作者模式”的文章。希望它提供的信息多于混淆:https ://zxq9.com/archives/1311

于 2017-08-15T12:52:01.233 回答
-2

请不要将其视为个人。您已要求提供反馈,我正在尝试将其提供给您。

快速查看文档和代码后,我认为您的库的主要问题是:

  1. 您在通常不需要的区域中引入了一些复杂性。在绝大多数 Erlang 程序中,您不想分析进程崩溃的原因。分析它很容易出错。所以“正常”的解决方案就是重启进程。如果你在这一点上引入任何逻辑,你可能也会引入一些错误。这样的程序更难推理,其优势至少是有争议的。

  2. 您假设退出原因是进程退出的原因。这不一定是真的。原因可能是从其链接的进程传播的。如果您想真正对所有可能的退出原因做出反应,则必须对所有进程退出原因、所有子退出原因、所有子退出原因等进行传递闭包。并且您必须在任何组件时更改它更改这是非常糟糕的态度,非常容易出错。并且引入的复杂性(见 1)爆炸得非常厉害。

  3. 你在内部逻辑应该保持理想的情况下引入一些“内省”逻辑——即,在导演的计划中,有一些关于在其模块之外使用的过程的内部工作的知识。这在某种程度上打破了封装。“普通”主管只知道如何启动流程,它不需要有关流程内部的更多信息。

  4. 最后但同样重要的是:您可能正在解决一个不存在的问题。与其开发一个全新的解决方案,您应该清楚地识别现有解决方案的问题,并尝试非常直接和最低限度地解决它们。

于 2017-08-14T07:39:02.563 回答