73 votes

Akka Acteur pas appelé à disparaître si une exception est levée

Je suis en train d'essayer de démarrer avec Akka et je suis confronté à un problème bizarre. J'ai le code suivant pour mon Acteur:

class AkkaWorkerFT extends Actor {
  def receive = {
    case Work(n, c) if n < 0 => throw new Exception("Negative number")
    case Work(n, c) => self reply n.isProbablePrime(c);
  }
}

Et c'est de cette façon que je commence mes travailleurs:

val workers = Vector.fill(nrOfWorkers)(actorOf[AkkaWorkerFT].start());
val router = Routing.loadBalancerActor(SmallestMailboxFirstIterator(workers)).start()

Et c'est de cette façon que je ferme tout bas:

futures.foreach( _.await )
router ! Broadcast(PoisonPill)
router ! PoisonPill

Maintenant ce qui se passe est que si j'envoie les travailleurs des messages avec n > 0 (aucune exception n'est levée), tout fonctionne bien et l'application s'arrête correctement. Cependant, dès que je l'ai envoyer un seul message qui entraîne une exception, l'application ne met pas fin car il y a toujours un acteur de course, mais je n'arrive pas à comprendre d'où il vient.

Dans le cas où il aide, c'est la pile du thread en question:

  Thread [akka:event-driven:dispatcher:event:handler-6] (Suspended) 
    Unsafe.park(boolean, long) line: not available [native method]  
    LockSupport.park(Object) line: 158  
    AbstractQueuedSynchronizer$ConditionObject.await() line: 1987   
    LinkedBlockingQueue<E>.take() line: 399 
    ThreadPoolExecutor.getTask() line: 947  
    ThreadPoolExecutor$Worker.run() line: 907   
    MonitorableThread(Thread).run() line: 680   
    MonitorableThread.run() line: 182   

PS: Le thread qui n'est pas appelé à disparaître n'est pas tout les threads de travail, parce que j'ai ajouté un postStop rappel, chacun d'eux s'arrête correctement.

PPS: Actors.registry.shutdownAll solutions de contournement du problème, mais je pense que shutdownAll ne doit être utilisé qu'en dernier recours, n'est-ce pas?

22voto

Arnon Rotem-Gal-Oz Points 8055

La bonne façon de gérer les problèmes à l'intérieur de akka acteurs n'est pas à jeter une exception, mais plutôt à définir superviseur des hiérarchies

"Lancement d'une exception dans le code simultané (supposons que nous utilisons non-acteurs liés), va tout simplement exploser le thread qui actuellement exécute l'acteur.

Il n'y a aucun moyen de savoir que les choses ont mal tourné (en dehors de l'inspection de la trace de la pile). Il n'y a rien que vous pouvez faire à ce sujet."

voir la Tolérance aux Pannes Par le Superviseur des Hiérarchies (1.2)

* note * le ci-dessus est vrai pour les anciennes versions d'Akka (1.2) Dans les versions plus récentes (par exemple 2.2) que vous souhaitez toujours définir un superviseur de la hiérarchie, mais il piège les Exceptions levées par les processus enfants. par exemple

class Child extends Actor {
    var state = 0
    def receive = {
      case ex: Exception ⇒ throw ex
      case x: Int        ⇒ state = x
      case "get"         ⇒ sender ! state
    }
  }

et dans le superviseur:

class Supervisor extends Actor {
    import akka.actor.OneForOneStrategy
    import akka.actor.SupervisorStrategy._
    import scala.concurrent.duration._

    override val supervisorStrategy =
      OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
        case _: ArithmeticException      ⇒ Resume
        case _: NullPointerException     ⇒ Restart
        case _: IllegalArgumentException ⇒ Stop
        case _: Exception                ⇒ Escalate
      }

    def receive = {
      case p: Props ⇒ sender ! context.actorOf(p)
    }
  }

voir la Tolérance aux Pannes Par le Superviseur des Hiérarchies (2.2)

2voto

tolitius Points 9816

La désactivation de l'enregistrement pour s'assurer que les choses résilier, tel que proposé par Viktor, c'est un peu étrange. Ce que vous pouvez faire à la place est de:

EventHandler.shutdown()

que proprement arrête tous les (logger) les auditeurs qui gardent le monde de la course après l'exception:

def shutdown() {
  foreachListener(_.stop())
  EventHandlerDispatcher.shutdown()
}

-2voto

andersoyvind Points 107

Tour de l'enregistreur akka.conf

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X