2017-06-22 28 views
0

我有一个使Http调用到外部服务的actor。有时服务会使用Http 404进行响应,并且有时也会出现http连接错误。再次重试时,这些都会消失。重试来自Akka Actor的http调用的正确方法是什么

什么是由演员重试请求的最佳方式。

什么,我能想到的是

  1. 使用主管战略和重启演员

  2. 使用在重试HTTP调用演员递归方法, 最大重试次数次

哪一个是正确的方法,1或2.我认为方法1对于像重试一个Http调用那样简单的事情来说是过度的。请分享你的建议。

回答

1

在我看来,你的两种方法都是有效的。

第一种方法是在我的眼睛拥抱失败,让演员只能做它应该做的(而不是让它处理重试等)

有方面要做到这一点更被动的方式一个整洁的东西建在Akka监督:BackoffSupervisor

在我看来,这是一个完美的适合问题,其中演员由于外部因素失败,它可能是有道理的等待一段时间再试一次(如在你的情况与http调用)。

从文档:

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

您可以定义一个最小和最大的补偿和监管当局尝试,直到达到最大重启演员之前两倍的等待时间。只有这样它才会停止尝试。

如果你喜欢你的第二个选择,我不会用递归方法去,但会schedule a message到演员本身在一段时间后再次尝试HTTP调用:

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

感谢您的建议 –

0

我倒是建议使用“之后”模式。这可以让你在失败的情况下重复你的请求。类似这样的:

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

这也是一个不错的选择 –

相关问题