在我的一个应用程序上使用 http4s-ember-server 时,我注意到这些异常不时出现在我的服务器日志中。
它们的奇怪之处在于它们不遵循我的记录器的附加程序或格式样式,它们只是像这样的纯文本,这些堆栈行位于单独的行中,因此我的 kubernetes 将它们作为单独的日志消息接收,而我的正常异常和任何异常应用程序日志被格式化为 JSON,甚至异常也能很好地集中在一个块中。所以这一定是来自低层次的东西。
我还注意到,我的 3 个非常相似的应用程序中只有 1 个抛出这些,所以它不可能是元/健康、就绪或构建信息端点。
java.nio.channels.ClosedChannelException
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.begin(AsynchronousSocketChannelImpl.java:118)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.shutdownInput(AsynchronousSocketChannelImpl.java:536)
at fs2.io.net.SocketCompanionPlatform$AsyncSocket.$anonfun$readChunk$3(SocketPlatform.scala:121)
at delay @ fs2.io.net.SocketCompanionPlatform$AsyncSocket.$anonfun$readChunk$2(SocketPlatform.scala:120)
at delay @ fs2.io.net.SocketCompanionPlatform$AsyncSocket.$anonfun$readChunk$1(SocketPlatform.scala:120)
at async @ fs2.io.net.SocketCompanionPlatform$AsyncSocket.readChunk(SocketPlatform.scala:114)
at flatMap @ fs2.io.net.SocketCompanionPlatform$BufferedReads.$anonfun$read$1(SocketPlatform.scala:82)
at delay @ fs2.io.net.SocketCompanionPlatform$BufferedReads.withReadBuffer(SocketPlatform.scala:52)
at flatten$extension @ org.http4s.ember.server.internal.Shutdown$$anon$1.<init>(Shutdown.scala:71)
at onError @ com.c1999.n1999.w1999.NWApp$.run(NWApp.scala:15) <- this is the only line that states my own code
at getAndSet @ org.typelevel.keypool.KeyPool$.destroy(KeyPool.scala:120)
有人在使用http4s服务器时遇到过这样的异常吗?
第 15 行左右的源代码如下所示
val program =
(for {
twoConfigs <- NWAppConfig
.load[IO]
.onError(error => logger.error(error)(show"failed to load config with: $error")) // line 15 here
.toResource
(appConfig, requestContextConfig) = twoConfigs
components <- NWComponents(appConfig, requestContextConfig)
_ <- logger.info("started").toResource
_ <- components.streamsJoined.compile.drain
.onError(error => logger.error(error)(s"error in nw: $error"))
.toResource
} yield ()).use_
我今天遇到了同样的问题,我花了一段时间才找到...这里发生的情况是终结器抛出一个(良性)异常,该异常通过 IOApp 中的
def reportFailure
直接打印到控制台您用来评估您的程序。这可以通过覆盖实现来重定向到您首选的日志库 - 如果您在 IOApp 中,那么就像一样简单
override protected def reportFailure(err: Throwable): IO[Unit] = myLogImpl(err)
或者,如果您使用
unsafeFoo
方法进行评估,则可以使用 val myRuntime = IORuntimeBuilder.apply().setFailureReporter(t => myLogImpl(t)).build()
构造自己的 IORuntime,而不是使用 IORuntime.global,并将其传递给不安全的方法,例如 .unsafeRunSync()(myRuntime)