2017-06-22 1 views
0

J'ai un acteur qui fait un appel HTTP à un service externe. Parfois, les services répondent avec Http 404 et il y a aussi parfois des erreurs de connexion http. Les deux disparaissent quand réessayé encore.Quelle est la bonne façon de réessayer des appels http d'Akka Actors

Quelle est la meilleure façon de réessayer la requête par l'acteur.

Ce que je peux penser est

  1. Stratégie superviseur et acteur de redémarrage

  2. Utilisez une méthode récursive dans l'acteur qui retente l'appel http, comptage max-retry fois

Quelle est l'approche correcte, 1 ou 2. Je pense que l'approche 1 sera une exagération pour quelque chose d'aussi simple que de réessayer un appel Http. S'il vous plaît partagez vos recommandations.

Répondre

1

À mon avis, vos deux approches sont valides.

La première approche est à mes yeux la façon plus réactive à faire en termes d'embrasser l'échec et de laisser l'acteur que faire ce qu'il est censé faire (au lieu de le laisser gérer retries etc.)

Il est A mon avis ceci est un ajustement parfait pour les problèmes où l'acteur échoue en raison de facteurs externes et il pourrait être logique d'attendre un certain temps pour essayer à nouveau (comme dans votre cas avec des appels http).

De la documentation:

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

Vous pouvez définir un minimum et un maximum et backoff le superviseur doublera le temps d'attente avant d'essayer de redémarrer l'acteur jusqu'à ce qu'il atteigne le maximum. Alors seulement, il cessera d'essayer.

Si vous préférez que votre deuxième option, je ne voudrais pas aller avec une méthode récursive, mais je schedule a message à l'acteur lui-même après une période de temps pour essayer à nouveau l'appel http:

system.scheduler.scheduleOnce(1 seconds, self, TryAgain) 
+0

Merci pour la suggestion –

0

Id suggérer d'utiliser le modèle "après". Cela vous permet de répéter votre demande en cas d'échec. Quelque chose comme ceci:

def retryRequest(ref: ActorRef, attemptsNumber: Int, step: Int)(
    implicit ac: ActorSystem): Future[HttpResponse] = { 

    implicit val timeout = Timeout(5 seconds) 
    implicit val ec = ac.dispatcher 

    val s1 = after[HttpResponse](5 seconds, ac.scheduler) { 
    Http().singleRequest(HttpRequest(uri = "http://akka.io")) 
    } 
    s1 flatMap { res => 
    res match { 
     case HttpResponse(StatusCodes.NotFound, headers, entity, _) => { 
     if(step < attemptsNumber) 
      retryRequest(ref, attemptsNumber, (step + 1)) 
     else 
      s1 
     } 
     case HttpResponse(StatusCodes.OK, headers, entity, _) => s1 
    } 
    } 
} 
+0

Ceci est également une bonne option –