【问题标题】:Scala - Retry HTTP request with timeoutScala - 超时重试HTTP请求
【发布时间】:2019-01-25 05:34:48
【问题描述】:

我希望创建一个服务,它向特定 URL 发出 HTTP 请求,如果它在 1 秒内没有得到结果,则该请求将超时,然后它将重试另一个请求,最多 3重试。

如何在 scala 中实现?

我正在查看 Akka HTTP 和 Play 的 WSClient 的文档,但我找不到任何地方提到它。

注意:如果请求对服务器产生副作用,我希望不成功的请求不会产生副作用。如何实现这种行为?有可能吗?

【问题讨论】:

  • 您可以将 Akka Actors 与带有 ASK 调用模式的 akka Http 一起使用,并将超时设置为 1 秒,在超时的情况下只需在监督策略中重新启动您的子 Actor 并再次发送新请求。我想这就是你要找的东西
  • @Raman Mishra 你能详细说明你的评论吗?另外,什么是监管策略?谢谢。
  • 您可以使用.toStrict 来限制您的httpResponse 并传递1 sec 的timeOut。在Failure 中写下您的重试逻辑。这是示例programcreek.com/scala/akka.http.scaladsl.model.HttpRequest。仅供参考doc.akka.io/docs/akka-http/current/routing-dsl/directives/…。我希望这会有所帮助。

标签: scala playframework request akka-http retry-logic


【解决方案1】:

你也可以使用来自akka模式的retry

import akka.pattern.{ask, pipe, retry}
import akka.actor.{Actor, ActorSystem, Props, Scheduler}
import akka.util.Timeout
import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext, Future}

class ClientActor extends Actor { //actor which times out 2 times and succeeds 3rd time

    var attempts = 0

    def receive = {
      case "request" =>
        this.attempts = attempts + 1
        if (attempts < 3) {
          Thread.sleep(2000)
          Future.failed(new Exception("timed out")) pipeTo sender
        } else {
          Thread.sleep(500)
          Future.successful(s"Successful in $attempts attempt") pipeTo sender
        }
        println(s"Attempt: $attempts")
    }
}


val system = ActorSystem("system") //actor system and needed implicits
implicit val ec: ExecutionContext = system.dispatcher 
implicit val timeout: Timeout = Timeout(1 seconds)
implicit val scheduler: Scheduler = system.scheduler


val client = system.actorOf(Props[ClientActor], "client-actor")

val future = retry(() => client ? "request", 3, 1 second) //create future which would retry 3 times

println(Await.result(future, 10 seconds)) //Would write "Successful in 3 attempt"

【讨论】:

  • 老实说,我正在尝试对 HTTP 请求使用重试。类似Http().singleRequest
【解决方案2】:

据我了解,您需要做的是:

步骤

  • 通过 HTTP 调用访问某些 API 的端点。
  • 如果没有在 1 秒内得到响应,则需要获取异常。
  • 出现异常需要重启服务,再次发送请求。

您可以通过 Akka Http 和 Akka Actors 的协作来做到这一点。

通过使用 Akka Actor,您可以告诉您的服务在遇到 TimeoutException 时需要做什么。您可以通过 Akka ask 模式进行 API 调用。 如果你会看到 Akka ask pattern here 的文档。它需要 Akka 询问超时,您可以将其设置为您想要的任何值,如果您在超时时没有收到响应,您将收到 AkkaAskTimeOutException,它将被您的子演员捕获,然后将其传递给主管演员, 当 Supervisor actor 捕捉到异常时,我们可以使用 supervison 策略并且可以指定需要做什么(重启、关闭、恢复等)。

监管策略:您可以阅读它here。以下是基于 akka actor 的应用程序的基本结构。

Supervisor Actor(我们在 Supervisor 中编写监督策略),它有子 Actor。

child1(业务逻辑) child2(业务逻辑)

【讨论】:

  • 你能把你说的翻译成示例代码吗?谢谢!
  • @TheOutsider 我以为您正在寻找设计模式。我会这样做的
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 2011-11-05
  • 2010-12-12
  • 2014-04-25
  • 1970-01-01
相关资源
最近更新 更多