【问题标题】:How to gracefully shutdown http4s如何优雅地关闭 http4s
【发布时间】:2020-05-25 23:14:28
【问题描述】:

我使用的是 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 server
def 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 秒请求的方法。

【问题讨论】:

    标签: scala http4s


    【解决方案1】:

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

    为方便起见,cats-effect 提供了一个 cats.effect.IOApp trait 返回 IO[ExitCode] 的抽象运行方法。一个 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 server
    
    

    【讨论】:

    • 不错的答案。请注意,一旦设置了信号,这将终止对服务器的所有打开请求。
    猜你喜欢
    • 2014-12-01
    • 2014-11-03
    • 1970-01-01
    • 2010-11-04
    • 2015-06-25
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多