2013-06-26 7 views
6

di Akka dice:Di chi è la responsabilità che sta creando i figli dell'attore di Akka quando fallisce? documentazione corretta citazione

la precisa sequenza di eventi durante un riavvio è il seguente: Sospendi l'attore (il che significa che non elaborerà normali messaggi fino ripresa), e ricorsivamente sospendere tutti i bambini .

Una citazione fuorviante dice:

Riprendendo un attore riprende tutti i suoi subalterni, di riavviare un attore comporta il riavvio tutti i suoi subordinati, allo stesso modo che chiude un attore sarà anche terminare tutti i suoi subordinati

Ciò che sospetto è che sia nostra responsabilità creare child (ren) nel metodo preStart perché il termine di Akka RESTART non è reSTART a meno che Creare i bambini in modo ricorsivo ed esplicito nel loro metodo genitore preStart().

Esempio (utilizzando Akka 2.0 & 2.2-SNAPSHOT): non importa quello che provo, i bambini sono sempre fermi, non riavviati mai in questo test case. Creo la relazione Supervisor ->First ->Second e creo un'eccezione nello Supervisor. Quello che succede è che supervisor viene riavviato e First & Second fermato.

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

Attore [Akka: // test/user/supervisore # 1.599.926,629 mila] inizia Attore [Akka: // test/user/supervisore/primo # 2.012.011,668 mila] inizia Attore [Akka: // test/user/supervisore/primo/secondo # 1750038710] inizia

gettando eccezione Attore [Akka: // test/user/supervisore # 1.599.926,629 mila] fermato [ERRORE] [2013/06/26 11: 11: 16,899] [test-akka.actor.default-dispatcher-4] [akka: // test/utente/supervisore] null java.lang.IllegalStateException a com.fg.mail.smtp.Inte grationSuite $ Supervisor $$ anonfun $ receive $ 1.applyOrElse (IntegrationSuite.scala: 40) at akka.actor.ActorCell.receiveMessage (ActorCell.scala: 498) a akka.actor.ActorCell.invoke (ActorCell.scala: 456) a akka.dispatch.Mailbox.processMailbox (Mailbox.scala: 237) a akka.dispatch.Mailbox.run (Mailbox.scala: 219) a akka.dispatch.ForkJoinExecutorConfigurator $ AkkaForkJoinTask.exec (AbstractDispatcher.scala: 386) a scala.concurrent.forkjoin.ForkJoinTask.doExec (ForkJoinTask.java:262) a scala.concurrent.forkjoin.ForkJoinPool $ WorkQueue.runTask (ForkJoinPool.java:975) a scala.concurrent.forkjoin.ForkJoinPool .runWorker (ForkJoinPool.java:1478) allo scala.concurrent.forkjoin.ForkJoinWorkerThread.run (ForkJoinWorkerThread.java: 104)

attore [Akka: // test/user/supervisore/primo/secondo # 1.750.038,71 mille] fermato attore [Akka: // test/user/supervisore/primo # 2.012.011,668 mila] fermato attore [Akka: // test/utente/supervisore # 1599926629] inizia

risposta

5

Il tuo sospetto è corretto. Se si osserva attentamente la descrizione in 7 passaggi del processo di riavvio su http://doc.akka.io/docs/akka/snapshot/general/supervision.html, verrà visualizzato:

2. ... il default è l'invio di richieste di terminazione a tutti i bambini ...

e

6. invia una richiesta di riavvio a tutti i bambini che non sono stati uccisi

Quindi, è necessario o sostituire il gancio del genitore preRestart per fermare Akka uccidere i figli, o ignorare postRestart per ricreare tutti i bambini che sono stati appena uccisi .

Ciò che si sceglie dipende davvero dalla semantica della propria applicazione. A volte è utile uccidere l'intera gerarchia e iniziare con una lavagna vuota, a volte no.

+0

Beh, è ​​un peccato che non ci sia una terza opzione che riavvii i bambini implicitamente ... Se ci pensi, l'unico modo sicuro di formare la gerarchia è creare attori discendenti nel metodo preStart() dei loro genitori. Qualsiasi altro modo sarebbe piuttosto complicato da raggiungere. – lisak

+0

La documentazione è piuttosto ambigua perché sta scrivendo sul "riavvio" ovunque e in realtà significa "chiamare" i metodi del ciclo di vita preRestart e postRestart, ma è tua responsabilità prendersi cura del reale re "STARTING" – lisak

+0

No? Se crei i tuoi figli nel costruttore o preStart, i bambini vengono ricreati automaticamente al riavvio del genitore. –

Problemi correlati