当父 actor 停止时不要立即停止子 Akka actor
Don't immediately stop child Akka actors when parent actor stopped
我有一个 actor p: ParentActor
,我想在它使用 postStop
方法停止时做一些清理工作。其中一项工作涉及向儿童演员 c: ChildActor
发送消息。之后,c
和 p
应该停止。但是,一旦 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 在 A
的 postStop
钩子被调用之前确实被停止了。一个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
给演员的结果。
我有一个 actor p: ParentActor
,我想在它使用 postStop
方法停止时做一些清理工作。其中一项工作涉及向儿童演员 c: ChildActor
发送消息。之后,c
和 p
应该停止。但是,一旦 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 在 A
的 postStop
钩子被调用之前确实被停止了。一个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, publishingTerminated
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
给演员的结果。