Akka的文档正确引用说:
重新启动期间的精确事件序列如下:暂停actor(这意味着它将不会处理正常消息,直到恢复),并递归暂停所有子节点 .
一个误导性的引述说:
恢复一个演员恢复其所有下属,重新启动演员需要重新启动其所有下属,同样终止一个演员也将终止其所有下属
我怀疑的是,我们有责任在 preStart
方法中创建子(ren),因为Akka的术语RESTART不是reSTART,除非您在其父 preStart()
方法中以递归和显式方式创建子项 .
示例(使用Akka 2.0和2.2-SNAPSHOT):无论我尝试什么,孩子总是刚刚停止,从未在此测试用例中重新启动 . 我创建 Supervisor
- > First
- > Second
关系并在 Supervisor
中抛出异常 . 会发生什么是 supervisor
重新启动并且 First
& Second
已停止 .
test("restart test") {
val system = ActorSystem("test")
val supervisor = system.actorOf(Props(new Supervisor), "supervisor")
supervisor ! CREATE(Props(new First), "first")
Thread.sleep(500)
val first = system.actorFor("akka://test/user/supervisor/first")
first ! CREATE(Props(new Second), "second")
Thread.sleep(500)
supervisor ! WTF
Thread.sleep(20000)
}
case object WTF
case class CREATE(p: Props, name: String)
class Supervisor extends Actor {
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10) {
case _: IllegalStateException => Restart
case _: IllegalArgumentException => Stop
case _: Exception => Restart
}
override def preStart() {
println(s"$self starts")
}
override def postStop() {
println(s"$self stopped")
}
override def receive = {
case WTF => println("throwing exception"); throw new IllegalStateException()
case CREATE(p, name) => context.actorOf(p, name)
}
}
class First extends Actor {
override def preStart() {
println(s"$self starts")
}
override def postStop() {
println(s"$self stopped")
}
override def receive = {
case WTF => println("throwing exception"); throw new IllegalStateException()
case CREATE(p, name) => context.actorOf(p, name)
}
}
class Second extends Actor {
override def preStart() {
println(s"$self starts")
}
override def postStop() {
println(s"$self stopped")
}
override def receive = {
case WTF => println("throwing exception"); throw new IllegalStateException()
case CREATE => sender ! "ok"
}
}
演员[akka:// test / user / supervisor#1599926629]启动演员[akka:// test / user / supervisor / first#2012011668]启动演员[akka:// test / user / supervisor / first / second#1750038710 ]开始抛出异常演员[akka:// test / user / supervisor#1599926629]停止[错误] [06/26/2013 11:11:16.899] [test-akka.actor.default-dispatcher-4] [akka: // test / user / supervisor]在com.fg.mail.smtp.IntegrationSuite上的null java.lang.IllegalStateException $ supervisor $$ anonfun $在akka.actor.ActorCell.receiveMessage上接收$ 1.applyOrElse(IntegrationSuite.scala:40)( ActorCell.scala:498)at akka.dispatch.ActionCell.invoke(ActorCell.scala:456)at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237)at akka.dispatch.Mailbox.run(Mailbox.scala:219 )在scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)的scala.concurrent.forkjoin.ForkJoinPool $ workQueue.runTask(ForkJoinPool . java:975)在scala.concurrent.forkjoin . ForkJoinPool.runWorker(ForkJoinPool.java:1478)在scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)演员[akka:// test / user / supervisor / first / second#1750038710]停止了演员[akka: // test / user / supervisor / first#2012011668]已停止Actor [akka:// test / user / supervisor#1599926629]启动
1 回答
你的怀疑是正确的 . 如果仔细查看http://doc.akka.io/docs/akka/snapshot/general/supervision.html上重启过程的7步说明,您将看到:
和
因此,您需要覆盖父级的
preRestart
挂钩以阻止Akka杀死子级,或者重写postRestart
以重新创建刚杀死的所有子级 .您选择哪个取决于您的应用程序的语义 . 有时,杀死整个层次结构并从空白的平板开始是有用的,有时候不是 .