7

Akka 的文档正确引用说:

重新启动期间的确切事件顺序如下:暂停actor(这意味着它不会处理正常消息,直到恢复),并递归地暂停所有子节点。

一个误导性的引用说:

恢复一个actor会恢复它的所有下属,重启一个actor需要重启它的所有下属,同样终止一个actor也会终止它的所有下属

我怀疑在preStart方法中创建 child(ren) 是我们的责任,因为 Akka 的术语RESTART不是 reSTART ,除非您在其父preStart()方法中递归且显式地创建子项。

示例(使用 Akka 2.0 和 2.2-SNAPSHOT):无论我尝试什么,在这个测试用例中,孩子总是只是停止,从未重新启动。我创建Supervisor-> First->Second关系并在Supervisor. 发生的事情supervisor是重新启动并停止FirstSecond

  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"
    }
  }

Actor[akka://test/user/supervisor#1599926629] 开始 Actor[akka://test/user/supervisor/first#2012011668] 开始 Actor[akka://test/user/supervisor/first/second#1750038710]开始

抛出异常 Actor[akka://test/user/supervisor#1599926629] 停止 [ERROR] [06/26/2013 11:11:16.899] [test-akka.actor.default-dispatcher-4] [akka:// test/user/supervisor] null java.lang.IllegalStateException at com.fg.mail.smtp.IntegrationSuite$Supervisor$$anonfun$receive$1.applyOrElse(IntegrationSuite.scala:40) at akka.actor.ActorCell.receiveMessage(ActorCell. scala:498) at akka.actor.ActorCell.invoke(ActorCell.scala:456) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237) at akka.dispatch.Mailbox.run(Mailbox.scala:219) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:第975章)java:1478) 在 scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

演员[akka://test/user/supervisor/first/second#1750038710] 停止演员[akka://test/user/supervisor/first#2012011668] 停止演员[akka://test/user/supervisor#1599926629]开始

4

1 回答 1

6

你的怀疑是正确的。如果您仔细查看http://doc.akka.io/docs/akka/snapshot/general/supervision.html上重启过程的 7 步描述,您会看到:

2. ...默认向所有孩子发送终止请求...

6. 向所有没有被杀死的孩子发送重启请求

因此,您需要覆盖父preRestart挂钩以阻止 Akka 杀死孩子,或者覆盖postRestart以重新创建刚刚被杀死的所有孩子。

您选择哪个实际上取决于您的应用程序的语义。有时杀死整个层次结构并从空白开始很有用,有时则不然。

于 2013-06-26T09:18:15.557 回答