我希望创建一个服务,它向特定 URL 发出 HTTP 请求,如果它在 1 秒内没有得到结果,则该请求将超时,然后它将重试另一个请求,最多重试 3 次。
如何在scala中实现这一点?
我正在查看 Akka HTTP 和 Play 的 WSClient 的文档,但我找不到任何地方提到它。
注意:如果请求对服务器产生副作用,我希望不成功的请求不会产生副作用。如何实现这种行为?甚至可能吗?
我希望创建一个服务,它向特定 URL 发出 HTTP 请求,如果它在 1 秒内没有得到结果,则该请求将超时,然后它将重试另一个请求,最多重试 3 次。
如何在scala中实现这一点?
我正在查看 Akka HTTP 和 Play 的 WSClient 的文档,但我找不到任何地方提到它。
注意:如果请求对服务器产生副作用,我希望不成功的请求不会产生副作用。如何实现这种行为?甚至可能吗?
您还可以使用来自 akka 模式的重试:
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"
据我了解您的问题,您需要做的是:
脚步
你可以通过 Akka Http 和 Akka Actors 的协作来做到这一点。
通过使用 Akka actor,您可以告诉您的服务在遇到 TimeoutException 时需要做什么。您可以通过 Akka ask 模式进行 API 调用。如果你会在这里看到 Akka ask 模式的文档。它需要 Akka 询问超时,您可以将其设置为您想要的任何值,如果您在超时时没有收到响应,您将收到 AkkaAskTimeOutException,它将被您的子演员捕获,然后将其传递给主管演员, 当 Supervisor actor 捕捉到异常时,我们可以使用 supervison 策略并且可以指定需要做什么(重启、关闭、恢复等)。
监督策略:你可以在这里阅读。实际上以下是基于 akka actor 的应用程序的基本结构。
监督演员(我们在监督者中编写监督策略),它有子演员。
child1(业务逻辑) child2(业务逻辑)