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

Akka HTTP client server idle timeouts are not working

我写了一个 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!")
    }
  }
}

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

错误 1

我在创建 ActorSystem 的实例时忘记将 appConf 作为参数传递,否则 ActorSystem 总是使用默认的 akka 配置创建。因此,始终确保在创建 ActorSystem 实例时传递 appConf ,否则您的 akka 配置将永远不会生效。

HelloWorld.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.

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

application.conf

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

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

Routes.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