2016-09-16 2 views
2

Ich habe Akka Supervisor Strategy verwendet, um Business-Logik-Ausnahmen zu behandeln.Akka Supervisor-Strategie - Korrekter Anwendungsfall

Als ich eine der berühmtesten Scala-Blogserien Neophyte las, fand ich ihn einen anderen Zweck für das, was ich schon immer gemacht habe.

Beispiel:

Lassen Sie uns sagen, dass ich ein HttpActor haben, die eine externe Ressource wenden sollte und falls es unten ist, werde ich eine Ausnahme, denn jetzt ein ResourceUnavailableException.

Wenn mein Supervisor das fängt, werde ich einen Neustart auf meinem HttpActor aufrufen, und in meinem HttpActor preRestart Methode werde ich eine schedulerOnce anrufen, um das zu versuchen.

Der Schauspieler:

class HttpActor extends Actor with ActorLogging { 

    implicit val system = context.system 

    override def preRestart(reason: Throwable, message: Option[Any]): Unit = { 
    log.info(s"Restarting Actor due: ${reason.getCause}") 
    message foreach { msg => 
     context.system.scheduler.scheduleOnce(10.seconds, self, msg) 
    } 
    } 

    def receive = LoggingReceive { 

    case g: GetRequest => 
     doRequest(http.doGet(g), g.httpManager.url, sender()) 
    } 

Ein Betreuer:

class HttpSupervisor extends Actor with ActorLogging with RouterHelper { 

    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 5) { 
     case _: ResourceUnavailableException => Restart 
     case _: Exception      => Escalate 
    } 

    var router = makeRouter[HttpActor](5) 

    def receive = LoggingReceive { 
    case g: GetRequest => 
     router.route(g, sender()) 

    case Terminated(a) => 
     router = router.removeRoutee(a) 
     val r = context.actorOf(Props[HttpActor]) 
     context watch r 
     router = router.addRoutee(r) 
    } 
} 

Was hier ist der Punkt?

Wenn meine doRequest Methode die ResourceUnavailableException auslöst, wird der Supervisor das bekommen und den Aktor neu starten, so dass er die Nachricht nach einiger Zeit erneut senden muss, laut dem Scheduler. Die Vorteile, die ich sehe, ist die Tatsache, dass ich kostenlos die Anzahl der Wiederholungen und eine nette Art, die Ausnahme selbst zu behandeln, bekomme.

Jetzt im Blog suchen, zeigt er einen anderen Ansatz, falls Sie einen erneuten Versuch Sachen benötigen, nur Meldungen wie diese zu senden:

def receive = { 
    case EspressoRequest => 
    val receipt = register ? Transaction(Espresso) 
    receipt.map((EspressoCup(Filled), _)).recover { 
     case _: AskTimeoutException => ComebackLater 
    } pipeTo(sender) 

    case ClosingTime => context.system.shutdown() 
} 

Hier bei AskTimeoutException der Future, er Rohre das Ergebnis als ein ComebackLater Objekt, das er dies tun wird Griff: Für mich

case ComebackLater => 
     log.info("grumble, grumble") 
     context.system.scheduler.scheduleOnce(300.millis) { 
     coffeeSource ! EspressoRequest 
     } 

das ist ziemlich viel, was Sie mit der Strategie Supervisor tun können, aber in eine manuell Art und Weise, mit eingebauten nicht in der Anzahl der Wiederholungen Logik.

Was ist der beste Ansatz hier und warum? Ist mein Konzept der Akka-Supervisor-Strategie völlig falsch?

Antwort

3

können Sie BackoffSupervisor verwenden:

bereitgestellt als Einbau-Muster die akka.pattern.BackoffSupervisor implementiert die sogenannte exponentielle Backoff Aufsicht Strategie, wieder ein Kind Schauspieler beginnt, wenn es fehlschlägt, jedes Mal mit einer wachsenden Zeitverzögerung zwischen Neustarts.

val supervisor = BackoffSupervisor.props(
    Backoff.onFailure(
    childProps, 
    childName = "myEcho", 
    minBackoff = 3.seconds, 
    maxBackoff = 30.seconds, 
    randomFactor = 0.2 // adds 20% "noise" to vary the intervals slightly 
).withAutoReset(10.seconds) // the child must send BackoffSupervisor.Reset to its parent 
    .withSupervisorStrategy(
    OneForOneStrategy() { 
     case _: MyException => SupervisorStrategy.Restart 
     case _ => SupervisorStrategy.Escalate 
    }))