Akka in der Dokumentation korrekt Zitat sagt:Wessen Verantwortung schafft die Kinder von Akka-Schauspielern, wenn es scheitert?
die genaue Abfolge der Ereignisse während eines Neustarts ist die folgende: die Schauspieler Suspend (was bedeutet, dass es nicht normal Nachrichten verarbeiten wird, bis wieder aufgenommen) und Suspend rekursiv alle Kinder .
Eine irreführende Zitat sagt:
wieder aufnehmen Schauspieler all seinen Untergebenen wieder aufgenommen wird, einen Schauspieler Neustart Neustart alle seine Untergebenen zur Folge hat, ähnlich einem Schauspieler beendet werden auch alle seine Untergebenen beenden
Was ich vermute, ist, dass es unsere Verantwortung ist, ein Kind in der preStart
-Methode zu erstellen, weil Akkas Begriff RESTART kein Neustart ist, es sei denn, y Sie erstellen die untergeordneten Elemente rekursiv und explizit in der übergeordneten Methode preStart()
.
Beispiel (mit Akka 2.0 & 2.2-SNAPSHOT): egal was ich versuche, Kinder werden immer nur gestoppt, nie in diesem Testfall neu gestartet. Ich erstelle Supervisor
->First
->Second
Beziehung und werfen Ausnahme in der Supervisor
. Was passiert ist, dass supervisor
wird neu gestartet und First
& Second
gestoppt.
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"
}
}
Schauspieler [akka: // Test/user/Supervisor # 1599926629] startet Schauspieler [akka: // Test/user/Supervisor/first # 2012011668] startet Schauspieler [akka: // Test/user/Supervisor/erste/zweite # 1750038710] startet
werfen Ausnahme Schauspieler [akka: // Test/user/Supervisor # 1599926629] gestoppt [ERROR] [2013.06.26 11: 11: 16,899] [test-akka.actor.default-dispatcher-4] [akka: // test/benutzer/supervisor] null java.lang.IllegalStateException unter com.fg.mail.smtp.Inte grationSuite $ Supervisor $$ anonfun $ erhalten $ 1.applyOrElse (IntegrationSuite.scala: 40) bei akka.actor.ActorCell.receiveMessage (ActorCell.scala: 498) um akka.actor.ActorCell.invoke (ActorCell.scala: 456) bei akka.dispatch.Mailbox.processMailbox (Mailbox.scala: 237) bei akka.dispatch.Mailbox.run (Mailbox.scala: 219) bei akka.dispatch.ForkJoinExecutorConfigurator $ AkkaForkJoinTask.exec (AbstractDispatcher.scala: 386) bei scala.concurrent.forkjoin.ForkJoinTask.doExec (ForkJoinTask.java:262) bei scala.concurrent.forkjoin.ForkJoinPool $ WorkQueue.runTask (ForkJoinPool.java:975) bei scala.concurrent.forkjoin.ForkJoinPool .runWorker (ForkJoinPool.java:1478) unter scala.concurrent.forkjoin.ForkJoinWorkerThread.run (ForkJoinWorkerThread.java: 104)
Schauspieler [akka: // Test/user/Supervisor/erste/zweite # 1750038710] gestoppt Schauspieler [akka: // Test/user/Supervisor/first # 2012011668] Schauspieler [akka gestoppt: // test/user/supervisor # 1599926629] startet
Nun, es ist eine Schande, es gibt keine dritte Option, die Kinder implizit einfach neu starten würde ... Wenn Sie darüber nachdenken, ist die einzige sichere Möglichkeit zur Bildung Hierarchie in der PreStart() -Methode ihrer Eltern. Jeder andere Weg wäre ziemlich kompliziert zu erreichen. – lisak
Die Dokumentation ist ziemlich zwiespältig, weil sie überall über "Neustart" schreiben und es bedeutet eigentlich "Aufruf" PreRestart und PostRestart Lifecycle-Methoden, aber es liegt in Ihrer Verantwortung, sich um die eigentliche "START" – lisak
Nein? Wenn Sie Ihre untergeordneten Elemente im Konstruktor oder preStart erstellen, werden die untergeordneten Elemente automatisch neu erstellt, wenn das übergeordnete Element neu gestartet wird. –