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

Erlang 如何检查流程是否由主管重新启动?,erlang,Erlang,更准确地说: 我有一个管理动态儿童数量的主管。我希望它在第一次添加和启动给定的子项时使用不同的init函数,而不是在以后重新启动时使用。或者,我可以使用相同的功能,如果流程有可能发现它已重新启动。从技术上讲,有一些副作用可用于确定流程是否由其主管重新启动或是否是第一次启动。例如,您可以检查流程的pid,并将其与主管的pid进行比较。然而,这是丑陋的,容易出错,并且与OTP原则不一致。实际上,监控程序本身可能已重新启动,或者应用程序或节点本身已重新启动。试图找出答案是徒劳的 相反,遵循OTP原则,

更准确地说:


我有一个管理动态儿童数量的主管。我希望它在第一次添加和启动给定的子项时使用不同的init函数,而不是在以后重新启动时使用。或者,我可以使用相同的功能,如果流程有可能发现它已重新启动。

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

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

想要知道某个进程是否已启动或重新启动的典型原因是,当它们首次启动时,它们必须执行一些不需要在重新启动时重做的操作。最后,您需要确保启动时需要完成的操作在终止时撤消,这样您的流程在所有情况下都可以在启动时执行相同的操作

例如,要做的是启动另一个进程(我们称之为B),然后在启动时将子进程和进程B链接起来,然后如果子进程终止,B也将终止(并且是交互的)。您必须将B进程的管理器配置为不重新启动其子进程(即使其成为临时进程)

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

增加工厂只会进一步推动问题,但不能完全解决问题。假设你有一个工厂,负责创造孩子。此过程可以保存子级的状态,并在重新启动时恢复它们。要实现这一目标,您需要:

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

你可能还想确保如果工厂倒闭,儿童也会死亡。要实现这一点,您应该执行这两个过程。因此,您可以通过将流程配置为陷阱退出(使用),而不是使用,将工厂配置为接收退出消息


然而,这并不能解决问题,因为工厂本身可能会异常终止。如果没有适当的清理,它将被其主管重新启动,所有状态都将丢失。因此,您需要确保当工厂终止时,需要在children start上执行的操作是撤消的。

我认为您应该首先澄清一个进程将死亡的原因,然后正确重启的相关策略是什么(您没有提供这方面的信息)。 然后,如果这些进程终止(例如会话超时)是应用程序的正常行为,那么我的意见是,您应该尝试将可能死亡的任务与负责存储状态的任务分开。 将信息保存在ets、DET或mnesia中也可能相关。
但正如Paul所说的,要坚持OTP原则。

受监督的流程就是OTP流程。因此,您的主管正在启动otp流程,如gen_server。要查看进程何时重新启动,请创建自己的名称服务器,然后使用gen_server:start_链接({via,YourModule,Identifier}…)跟踪重新启动。

似乎无法获取有关进程重新启动的信息:进程状态为本地(您不能使用它存储重新启动计数),并且主管模块不提供此类功能。但您可以使用单独的流程/ets表/文件来存储所需信息。感谢您提供了许多重要的见解,但似乎它们与我的案例并不完全相关。在流程生命周期中,它获得了一定的(简单的)状态。重新启动后应将其保留并还原。尝试还原全新流程的状态会导致死锁。原因:所有描述的流程都是由gen_server创建的,该服务器充当它们的工厂。它也是修改其状态的流程。因此,调用层次结构为:sth->factory(创建进程)->supervisor(add child)->child(init)->factory(modify my state)=deadlock=timeout。我更新了响应以考虑工厂示例。可以使用异步消息避免死锁。子进程可以在init处理程序中向自己发送异步消息(使用
gen\u server:cast(self(),message)
)相应的
handle\u cast
处理程序将从工厂获取状态。或者,如果主管永远不会重新启动子进程,工厂可以在启动子进程后立即提供状态。