Akka HTTP客户端服务器空闲超时不起作用

ut6juiuv  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(149)

我写了一个API,它需要几分钟来创建一个响应。这显然会导致连接重置:

curl: (56) Recv failure: Connection reset by peer

我已经尝试了Akka HTTP的超时配置,但似乎没有解决上述问题。

akka.http.server.idle-timeout = 600 s
akka.http.client.idle-timeout = 600 s

akka.http.server.request-timeout = 600 s

我怀疑问题出在idle-timeout上,但上面的配置似乎没有任何影响。
谁能告诉我问题出在哪里?
我尝试了一个相反的场景,我把idle-timeout设置为5s,这是为了重置连接,但即使这样也不起作用。不知道这里到底是什么问题。有人能解释一下这种行为吗?我该如何修复它?
我已经实现了一个完整的工作示例,任何人都可以尝试使用here
application.conf

akka.http.server.idle-timeout = 5 s
akka.http.client.idle-timeout = 5 s

akka.http.server.request-timeout = 600 s

helloworld {
  http {
    interface = "127.0.0.1"
    port = "8066"
  }
}

Routes.scala

package com.codingkapoor.helloworld.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import akka.stream.ActorMaterializer
import scala.concurrent.duration._

private[helloworld] trait Routes extends JsonSupport {

  implicit lazy val timeout: Timeout = Timeout(5.minute)

  implicit def materializer: ActorMaterializer

  lazy val routes: Route = pathSingleSlash {
    get {
      Thread.sleep(180000)
      complete(StatusCodes.OK, "Hello World!")
    }
  }
}
xiozqbni

xiozqbni1#

有两个错误,我发现,修复这解决了问题。

错误1

在创建ActorSystem的示例时,我忘记了传递appConf作为参数,没有它,ActorSystem总是用默认的akka配置来创建的。因此,在创建ActorSystem的示例时,一定要确保传递appConf,否则你的akka配置将永远不会生效。

你好世界.Scala

val appConf = RuntimeEnvironment.appConf

implicit val system = ActorSystem("helloworld", appConf)

错误2

在这个问题中,我把Thread.sleep放到了路由线程中,这导致idle-timeout只有在睡眠结束后才能访问日志。
我想说的是,当我在没有appConf的情况下创建ActorSystem时,应该使用1 min的默认idle-timeout,但因为我在路由线程中放置了3 minThread.sleep,所以1 minidle-timeout只在3 mins之后才被记录。


# Despite idle-timeout being 1 min, the following exception was getting

# logged only after 3 mins

Caused by: akka.http.impl.engine.HttpIdleTimeoutException: 
  HTTP idle-timeout encountered, no bytes passed in the last 1 minute.
  This is configurable by akka.http.[server|client].idle-timeout.

模拟延迟响应的最好方法是使用如下所示的future来完成请求。这里我设置了4 minsidle-timeout3 minsrequest-timeout。这会导致请求总是得到服务!希望这能澄清。

应用程序.conf

akka.http.server.idle-timeout = 240000 s
akka.http.client.idle-timeout = 240000 s

akka.http.server.request-timeout = 600 s

路径.scala

lazy val routes: Route = pathSingleSlash {
    get {
        complete {
            Future.unit.map(_ => Thread.sleep(180000))
                       .map(_ => StatusCodes.OK -> "Hello World!")
        }
    }
}

整个想法是,如果idle-timeout大于request-timeout,您的请求至少有机会得到服务,否则它们将被丢弃!

idle timeout (10mins)    ------>

request timeout (5 mins) --->

idle timeout (1 min)     --->

request timeout (5 mins) ------>

您可以找到工作解决方案here

相关问题