PoisonPill没有像预期的那样杀死Akka演员系统

时间:2017-08-02 16:29:48

标签: scala akka

我正在尝试在我的Scala 2.11应用程序(使用Akka)中将一个子actor发送给顶级actor(PoisonPill)并关闭整个JVM进程

我上传了this repo,以便您可以重现我所看到的内容。只需克隆它并运行Master

但基本上我们有./gradlew run

Driver

然后在object Driver extends App { println("Starting upp the app...") lazy val cortex = ActorSystem("cortex") cortex.registerOnTermination { System.exit(0) } val master = cortex.actorOf(Props[Master], name = "Master") println("About to fire a StartUp message at Master...") master ! StartUp println("Fired! Actor system is spinning up...") }

Child

当我运行class Child extends Actor { override def receive = { case MakeItHappen => println("Child will make it happen!") context.parent ! PoisonPill } } 时,我看到以下输出:

./gradlew run

然而,JVM进程永远不会关闭。我本来期望./gradlew run Starting a Gradle Daemon (subsequent builds will be faster) :compileJava NO-SOURCE :compileScala UP-TO-DATE :processResources NO-SOURCE :classes UP-TO-DATE :run Starting upp the app... About to fire a StartUp message at Master... Fired! Actor system is spinning up... Stage Director has received a command to start up the actor system! Child will make it happen! <==========---> 80% EXECUTING > :run 杀死PoisonPill(以及Master),退出/关闭actor系统,然后Child命令(我在之后注册)演员系统终止)启动并退出JVM进程。

谁能告诉我们这里发生了什么?

1 个答案:

答案 0 :(得分:2)

您正在停止Master,但您没有关闭ActorSystem。即使Master是顶级演员(即由system.actorOf创建的演员),停止它也不会终止ActorSystem(请注意Master本身有parent,所以它不是演员层次结构中的“最高”演员。)

终止ActorSystem的正常方法是致电terminate。如果您希望在Master停止后关闭整个系统,那么您可以覆盖Master的{​​{1}}挂钩并在那里调用postStop。但是,在actor的生命周期钩子中调用context.system.terminate()是有风险的。例如,如果在actor中抛出异常,并且actor的监督策略将其停止,那么您可能不打算在此时关闭整个系统。这样的设计不是很有弹性。

查看此pattern以“在合适的时间关闭演员系统。”