首页 > 解决方案 > 2个标准输出源 - 中断写入问题

问题描述

我们在 k8s 中有几个 Spring Boot 应用程序,它们将应用程序日志和 tomcat 访问日志都写入标准输出。

当日志吞吐量非常高(由请求数量或应用日志数量引起)时,有时会发生日志行被中断的情况。

在我们的例子中,这看起来像这样:

[04/Aug/2021:13:39:27 +0200] - "GET /some/api/path?listWithIds=22838de1,e38e2021-08-04 13:39:26.774 ERROR 8 --- [ SomeThread-1] a.b.c.foo.bar.FooBarClass      : Oh no, some error occured
e7fb,cd089756,1b6248ee HTTP/1.1" 200 (1 ms)

期望的状态:

[04/Aug/2021:13:39:27 +0200] - "GET /some/api/path?listWithIds=22838de1,e38ee7fb,cd089756,1b6248ee HTTP/1.1" 200 (1 ms)
2021-08-04 13:39:26.774 ERROR 8 --- [ SomeThread-1] a.b.c.foo.bar.FooBarClass      : Oh no, some error occured

有什么方法可以防止这种情况发生吗?也许是 tomcat、java 或 spring-boot 设置?或容器级别的设置,以确保正确缓冲每一行

标签: javaspringspring-boottomcatkubernetes

解决方案


System.out最好是线程安全的,但这并不意味着当多个线程写入时它不会交错文本。至少出于这个原因,将应用程序日志和 HTTP 服务器日志写入同一个流对我来说似乎是一个错误,但其他原因也是如此。

如果您想将日志聚合在一起,使用字符流不是这样做的方法。相反,您需要使用一个日志框架来理解单独的日志事件,它可以连贯地写入该聚合目标。

您可能需要编写自己的AccessLogValve子类,该子类使用您的日志框架,而不是直接写入流。


推荐阅读