Akka aktor nie kończy, jeśli wyjątek zostanie wyrzucony

Obecnie próbuję zacząć od Akki i mam dziwny problem. Mam następujący kod dla mojego aktora:

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);
  }
}

I tak zaczynam swoich pracowników:

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

I tak wszystko zamykam:

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

Teraz dzieje się tak, jeśli wysyłam wiadomości workerów z n > 0( żaden wyjątek nie jest wyrzucany), wszystko działa dobrze i aplikacja wyłącza się poprawnie. Jednak jak tylko wyślę mu pojedynczą wiadomość, która spowoduje wyjątek, aplikacja nie kończy się, ponieważ nadal działa aktor, ale nie mogę rozgryźć, skąd pochodzi.

W przypadku, gdy to pomaga, jest to stos wątku, o którym mowa:

  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: wątek, który się nie kończy, nie jest żadnym z wątków roboczych, ponieważ dodałem poststop callback, każdy z nich zatrzymuje się poprawnie.

PPS: Actors.registry.shutdownAll obejdzie problem, ale myślę, że shutdownAll powinien być używany tylko w ostateczności, prawda?

Author: fresskoma, 2011-05-30

3 answers

Prawidłowym sposobem radzenia sobie z problemami wewnątrz aktorów akka nie jest rzucanie wyjątków, ale raczej ustawianie hierarchii przełożonych

" rzucanie wyjątku w kodzie współbieżnym (Załóżmy, że używamy niezwiązanych aktorów), po prostu wysadzi wątek, który obecnie / align = "left" /

Nie ma sposobu, aby dowiedzieć się, że coś poszło nie tak (oprócz sprawdzanie śladu stosu). Nic na to nie poradzisz."

Zobacz Tolerancja Przez Hierarchię Przełożonych (1.2)

* Uwaga * powyższe dotyczy starych wersji Akka (1.2) W nowszych wersjach (np. np.

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

I w przełożonym:

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

Zobacz Tolerancja Błędów Przez Hierarchię Przełożonych(2.2)

 21
Author: Arnon Rotem-Gal-Oz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-02 16:35:07

[2]}Wyłączenie logowania, aby upewnić się, że wszystko się skończy, jak zaproponował Viktor, jest trochę dziwne. Co możesz zrobić zamiast tego to:

EventHandler.shutdown()

To całkowicie wyłącza wszystkich (loggera) słuchaczy, którzy trzymają świat za wyjątkiem:

def shutdown() {
  foreachListener(_.stop())
  EventHandlerDispatcher.shutdown()
}
 2
Author: tolitius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 19:36:25

Obrót loggera w akka.conf

 -1
Author: andersoyvind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-29 20:24:37