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 min
的 Thread.sleep
放在路由线程中,1 min
的 idle-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 mins
的 idle-timeout
和 3 mins
的 request-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。
我写了一个 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 min
的 Thread.sleep
放在路由线程中,1 min
的 idle-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 mins
的 idle-timeout
和 3 mins
的 request-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。