首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何优雅地关闭http4s

如何优雅地关闭http4s
EN

Stack Overflow用户
提问于 2020-03-16 07:12:40
回答 1查看 1.7K关注 0票数 7

我正在使用http4s BlazeServer 0.21,我如何才能优雅地关闭呢?我想拒绝所有即将到来的请求,并将处理未完成的请求和响应保留在硬关闭时间内。

我尝试用serveWhile启动服务器并设置一个shutdownHook SignallingRef。服务器流和中间件按预期推迟(因此我们的度量和日志中间件仍然记录此响应)

代码语言:javascript
复制
//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 server
代码语言:javascript
复制
def shutdown[F[_]: Effect](interrupter: SignallingRef[F, Boolean]): F[Unit] = {
  LiftIO[F].liftIO(IO {
    sys.addShutdownHook {
      ...
      interrupter.set(true)
    }
  })
}
代码语言:javascript
复制
object Server extends IOApp {
  def run(args: List[String]): IO[ExitCode] =
    serverStream[IO].compile.drain.as(ExitCode.Success)
}

但是http服务器不像我预期的那样工作,似乎http4s的内部ServerChannel有自己的shutdownHook,并且已经取消了所有的响应。

有什么建议/解决办法吗?或者仅仅是一种保持和不终止x秒请求的方法也是值得赞赏的。

EN

回答 1

Stack Overflow用户

发布于 2020-05-25 15:14:28

为了方便起见,服务器连接了SIGTERM。

作为一种方便,convenience提供了一个cats.effect.IOApp特性,并提供了一个返回IOExitCode的抽象运行方法。IOApp运行进程并添加一个JVM关闭钩子来中断无限进程,并在接收到SIGTERM时优雅地关闭服务器。

如果您想使用URL (例如http://localhost:8080/ops/shutdown/true )关闭,它也能工作。

代码很直接,

代码语言:javascript
复制
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
}

服务器的设置和你的类似,

代码语言:javascript
复制
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 server
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60701688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档