如何使用Erlang OTP管理程序行为重启具有自定义状态的子项?

时间:2012-11-26 10:32:06

标签: erlang otp

我正在使用OTP管理员行为来监督和重启子进程。然而,当孩子死亡时,我想以崩溃前的状态重新启动它。

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

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

  1. 主管创建一个ETS表并将表标识符传递给每个子项
  2. 子进程启动,并根据子进程的某些相关属性,查询ETS表以查找要加载的状态
  3. 每次孩子的状态发生变化时,都会将其写入ETS表
  4. 所以,如果我有12个代表Cobol的12个部落的子进程,每个进程都会使用它的名字作为ETS表的关键,以便在启动时查找前一个化身留下的状态。每当状态发生变化时,每个进程都会更新表(再次使用其名称作为键)。

    主管将自动重启被杀死的孩子,上面的步骤2将在孩子的init方法中执行。第3步将在子句的handle_call,handle_cast和handle_info方法中处理(我正在对您的进程的性质做出一些假设)。通过主管可以使用多种重启策略,如果需要,甚至可以重新启动兄弟姐妹。

    希望这会给你一些想法。

答案 2 :(得分:0)

我认为这种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)?我怀疑那是可能的。