如何使用Erlang OTP主管行为重新启动具有自定义状态的子项?

我正在使用OTP主管行为来监督和重新启动子进程。 但是,当孩子死亡时,我想用崩溃前的相同状态重新启动它。

如果我编写自己的自定义主管,则可以收到{EXIT,Pid,Reason}消息并对其执行操作。 当使用OTP管理员行为时,它全部由OTP管理,我无法控制它。 我实现的唯一回调函数是init。

在这种情况下是否有任何标准方法? 如何自定义由otp supervisor动态重启的子项的状态? 如何使用OTP获得终止进程的Pid? 或者也许有可能在终止之前获得孩子的状态,然后将孩子恢复到它坠毁之前的状态?


可能以相同的状态重新启动不是个好主意。 可能导致错误的状态导致进程崩溃,如果以相同的状态重新启动,它将再次崩溃。 但是,如果你想要这个,使用外部资源来保存它(如ets或mnesia)。


在不知道你在做什么的任何细节的情况下,我可以想象一个这样的世界:

  • 主管创建一个ETS表并将表标识符传递给每个孩子
  • 一个孩子的过程开始,根据孩子的某些相关属性,咨询ETS表以寻找要加载的状态
  • 每当一个孩子的状态改变时,它就会将它写入ETS表
  • 因此,如果我有12个代表Cobol 12个部落的子进程,每个进程都会使用它的名称作为ETS表的关键字,以查找在开始时前一个化身留下的状态。 每当它的状态改变时,每个进程都会更新表(再次使用其名称作为键)。

    主管会自动重新启动一个被杀死的孩子,上面的步骤2将在孩子的init方法中执行。 第3步将在儿童的handle_call,handle_cast和handle_info方法中处理(我正在对您的过程的性质做一些假设)。 如果需要,可以通过管理员提供许多重新启动策略,甚至可以重新启动同级。

    希望这给你一些想法。


    我认为这种OTP主管行为的自定义不能轻易完成。 OTP主管的设计方式迫使我遵循一些严格的设计惯例。 在这种情况下,最重要的一点是监督员不应该做任何事情,除了监控其子女并在异常终止的情况下重新启动它们。 监督人员不应该有额外的逻辑,不要在监督人员中引入任何监督树和容错的关键部分的错误。

    当孩子死亡时,我想用崩溃前的相同状态重新启动它 - 这通常是不好的做法,因为孩子可能因为在终止之前已经损坏的状态而死亡,并且在这种情况下以相同的状态重新启动它肯定会造成问题

    在这种情况下是否有任何标准方法? 在重新启动它们之前,自定义主管内儿童的状态会违反主管的良好设计规范。 因此,这类任务通常以不同方式完成,例如通过引入另一个进程,例如gen_server,负责通过主管(supervisor:start_child)启动子进程,并在所有进程上维护监视器。 这个额外的过程可以在开始新的孩子之前做任何必要的定制。

    如何使用OTP获得终止进程的Pid? - 在通过主管start_child启动孩子的额外过程中,您可以监控他们,然后收听DOWN消息。 例如,在gen_server的情况下,您可以使用如下的handle_info函数:

    handle_info({'DOWN', Ref, process, _Pid, _}, S) -> 
        handle_down_worker(Ref, _Pid, S).
    

    或者也许有可能在终止之前获得孩子的状态,然后将孩子恢复到它坠毁之前的状态? - 如果我错了,请纠正我的错误,但我认为在Erlang和'DOWN'消息中,不可能在终止之前发送子进程的状态。 如果可能的话,我可以只处理类似于{DOWN,Pid,Reason,State}的消息,并用相同的状态或部分状态重新启动进程。 但是,我在想......你怎么能保持突然死去的孩子的状态,例如在出口处死亡(Pid,kill)? 我怀疑这是可能的。

    链接地址: http://www.djcxy.com/p/38201.html

    上一篇: How to restart child with custom state using Erlang OTP supervisor behaviour?

    下一篇: Why my supervisor terminating?