我正在使用http4s BlazeServer 0.21,我如何才能优雅地关闭呢?我想拒绝所有即将到来的请求,并将处理未完成的请求和响应保留在硬关闭时间内。
我尝试用serveWhile启动服务器并设置一个shutdownHook SignallingRef。服务器流和中间件按预期推迟(因此我们的度量和日志中间件仍然记录此响应)
//serverStream
for {
signal <- fs2.Stream.eval(SignallingRef[F, Boolean](false))
exitCode <- fs2.Stream.eval(Ref[F].of(ExitCode.Success))
_ <- fs2.Stream.eval(shutdown(signal))
server <- BlazeServerBuilder[F]
.bindHttp(8080, "0.0.0.0")
.withHttpApp(httpApp)
.serveWhile(signal, exitCode)
} yield serverdef shutdown[F[_]: Effect](interrupter: SignallingRef[F, Boolean]): F[Unit] = {
LiftIO[F].liftIO(IO {
sys.addShutdownHook {
...
interrupter.set(true)
}
})
}object Server extends IOApp {
def run(args: List[String]): IO[ExitCode] =
serverStream[IO].compile.drain.as(ExitCode.Success)
}但是http服务器不像我预期的那样工作,似乎http4s的内部ServerChannel有自己的shutdownHook,并且已经取消了所有的响应。
有什么建议/解决办法吗?或者仅仅是一种保持和不终止x秒请求的方法也是值得赞赏的。
发布于 2020-05-25 15:14:28
为了方便起见,服务器连接了SIGTERM。
作为一种方便,convenience提供了一个cats.effect.IOApp特性,并提供了一个返回IOExitCode的抽象运行方法。IOApp运行进程并添加一个JVM关闭钩子来中断无限进程,并在接收到SIGTERM时优雅地关闭服务器。
如果您想使用URL (例如http://localhost:8080/ops/shutdown/true )关闭,它也能工作。
代码很直接,
class SysOpsEndpoints[F[_]: Sync](signal: SignallingRef[F, Boolean]) extends Http4sDsl[F] {
private def shutdown: HttpRoutes[F] =
HttpRoutes.of[F] {
case GET -> Root / "shutdown" / shutdown =>
for {
_ <- signal.set(Try(shutdown.toBoolean).getOrElse(false))
result <- Ok(s"Shutdown: $shutdown")
} yield result
}
}
object SysOpsEndpoints {
def endpoints[F[_]: Sync](signal: SignallingRef[F, Boolean]): HttpRoutes[F] =
new SysOpsEndpoints(signal).shutdown
}服务器的设置和你的类似,
for {
signal <- fs2.Stream.eval(SignallingRef[F, Boolean](false))
exitCode <- fs2.Stream.eval(Ref[F].of(ExitCode.Success))
httpApp = Router(
"/ops" -> SysOpsEndpoints.endpoints(signal)
).orNotFound
server <- BlazeServerBuilder[F](serverEc)
.bindHttp(8080, "0.0.0.0")
.withHttpApp(httpApp)
.serveWhile(signal, exitCode)
} yield serverhttps://stackoverflow.com/questions/60701688
复制相似问题