当父 actor 停止时不要立即停止子 Akka actor

Don't immediately stop child Akka actors when parent actor stopped

我有一个 actor p: ParentActor,我想在它使用 postStop 方法停止时做一些清理工作。其中一项工作涉及向儿童演员 c: ChildActor 发送消息。之后,cp 应该停止。但是,一旦 context.stop(p) 被调用,c 似乎立即停止并且无法接收消息。

下面是我想做的一个例子:

class ParentActor extends Actor {
  ...
  override def postStop {
    logger.info("Shutdown message received. Sending message to child...")
    val future = c ? "doThing"
    logger.info("Waiting for child to complete task...")
    Await.result(future, Duration.Inf)
    context.stop(c)
    logger.info("Child stopped. Stopping self. Bye!")
    context.stop(self)
  }
}

错误消息结果:

[ERROR] [SetSystem-akka.actor.default-dispatcher-5] [akka://SetSystem/user/ParentActor] Recipient[Actor[akka://SetSystem/user/ParentActor/ChildActor#70868360]] had already been terminated. Sender[Actor[akka://SetSystem/user/ParentActor#662624985]] sent the message of type "java.lang.String".

另一种方法是发送 p 一条消息说要关闭,并因此执行上述操作,但使用内置的停止功能似乎更好。

PS。这是一个新的应用程序,因此欢迎设计替代方案。

当一个 actor A 被停止时,它的 children 在 ApostStop 钩子被调用之前确实被停止了。一个actor停止时的事件顺序如下(来自官方documentation):

Termination of an actor proceeds in two steps: first the actor suspends its mailbox processing and sends a stop command to all its children, then it keeps processing the internal termination notifications from its children until the last one is gone, finally terminating itself (invoking postStop, dumping mailbox, publishing Terminated on the DeathWatch, telling its supervisor).

覆盖 parent 的 postStop 对您没有帮助,因为您想要的关闭程序包括向 child 发送消息并等待回复。当parent终止时,child在parent的postStop为运行之前停止。

如您所述,向 ParentActor 发送特定消息以启动关机是另一种方法。像下面这样的东西会起作用:

import akka.pattern.pipe

class ParentActor extends Actor {
  ...
  def receive = {
    case Shutdown =>
      (c ? DoYourThing).mapTo[ThingIsDone].pipeTo(self)
    case ThingIsDone =>
      logger.info("Child has finished its task.")
      context.stop(self)
    case ...
  }
}

请注意,应避免在 actor 中使用 Await。相反,pipe Future 给演员的结果。