如何检查过程是否由主管重新启动?

更确切地说:

我有一个负责儿童动态数量的主管。 当给定的孩子被添加并在第一时间启动时,我希望它使用不同的初始化函数,而不是在以后会发生的所有重新启动。 或者,如果流程可能发现它已重新启动,则可以使用相同的功能。


从技术上讲, 有副作用可以用来确定一个过程是否由其主管重新启动,或者是否是第一次启动。 例如,您可以检查进程的PID并将其与主管的PID进行比较。 然而,这是丑陋的,容易出错的,并且与OTP原则不一致 。 事实上,管理员本身可能已经重新启动,或者应用程序或节点本身。 试图找出答案是徒劳的。

相反,遵循OTP原则,您必须确保受监督的流程执行相同的任务,无论它们是首次启动还是重新启动 。 这可以通过适当的监督树来处理进程之间的依赖关系。

希望查明进程是否已启动或重新启动的典型原因是因为当它们首次启动时,它们必须执行一些在重新启动时不需要重做的内容。 最终, 您需要确保终止时需要完成的任务需要完成 ,因此您的流程在所有情况下都可以在开始时执行相同的操作。

例如,要做什么可能是启动另一个进程(让我们称它为B),然后在开始时将孩子和进程B联系起来,然后孩子终止,B也将终止(并且相互)。 您将不得不配置B进程的主管,以便不重启其子项(即使其成为临时的)。

(根据下面的第一条评论进行更新)

添加工厂只会进一步推动问题,但并不能完全解决问题 。 假设你有一个负责创建孩子的工厂。 这个过程可以保存儿童的状态并在重新启动时恢复它们。 为了达到这个目的,你会:

  • 确保主管不重新启动孩子(他们应该被指定为临时);
  • 在用erlang:monitor/2创建子项后创建一个监视器。 每当孩子终止时,工厂都会收到一条消息。 然后它可以重新启动孩子并为其提供状态;
  • 让孩子们定期向工厂发送所需的信息。
  • 请注意,为了提高内存效率,您应该在单独的消息中恢复工厂的进程状态。 事实上,如果您将保存的状态置于规范中,主管将保留副本。

    如果工厂死亡,你也可能想确保孩子死亡。 要做到这一点,你应该链接两个过程。 因此,您可以将工厂配置为陷阱出口(使用erlang:process_flag/2 )来配置工厂以接收EXIT消息,而不是使用erlang:monitor/2

    然而,这并不能解决问题,因为工厂本身可能会异常终止。 它将由其主管重新启动,并且所有状态都将丢失,没有适当的清理。 因此,当工厂终止时,您需要确保在儿童开始时需要完成的工作取消。


    我想你应该首先澄清为什么一个过程会死亡,然后有什么相关的策略才能正常重启(你不提供这方面的信息)。 然后,如果这些进程终止(例如会话超时)是应用程序的正常行为,那么我认为您应该尝试将可能死于负责存储状态的任务分离出来。 将信息保存在ets,dets或mnesia中可能也是相关的。 但是,正如Paul所说的那样,尽量遵守OTP原则。


    受监督的流程是OTP流程。 因此你的主管开始像gen_server这样的进程。 要查看何时重新启动进程,请创建您自己的域名服务器,然后使用gen_server:start_link({via,YourModule,Identifier} ...来跟踪重新启动。

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

    上一篇: How to check whether the process was restarted by supervisor?

    下一篇: How to atomatically delete specs of terminated children in a dynamic supervisor