在Netty或任何其他非阻塞IO服务器上使用Logback MDC

6

Logback MDC(Mapped Diagnostic Context)利用 threadLocal(据我所知)使得它在同一线程执行的所有日志语句中都可以访问。

我的问题是,像Netty或Undertow这样的非阻塞IO服务器端运行时是否能够像在Tomcat中一样使用logback MDC? 如果可以,那么它是如何工作的,因为Netty/Undertow不像Tomcat一样遵循一个请求一个线程的规则。

我正在尝试在MDC中放置traceID,以便我可以在像Splunk/ELK这样的集中式日志记录系统中跟踪多个微服务/流水线监听器中的单个事务轨迹上的所有日志。

2个回答

7

我对直接使用netty不是很熟悉,但我知道可以在异步代码中使用logback MDC。不过这并不容易。

基本上,您需要将traceId与请求/连接绑定起来,并且每次开始处理该连接时,都要在当前线程的MDC中设置traceId。

如果您正在使用线程池,则可以使用自定义Executor来完成此操作,该Executor从当前线程本地存储中获取当前状态(例如traceId),并创建一个包装的Runnable或Callable,在运行之前将线程本地存储设置为先前检索到的值。然后将该包装Runnable转发到委托Executor。

您可以在此处查看如何执行此操作:https://github.com/lucidsoftware/java-thread-context/blob/master/thread-context/src/main/java/com/github/threadcontext/PropagatingExecutorService.java

实际上,根据您的需求,您可能能够使用java-thread-context项目。


这被称为传播线程池,这是我们如何在池中的所有线程上实现可用的MDC。 - Alexander.Furer

1
如您所提到的,MDC实现基于ThreadLocal,因此不适用于Reactor。
如果使用Reactor(我假设您是通过标签使用它),我的建议是:
  1. 使用MonoFlux中提供的Context(文档在这里),以便在执行期间存储traceId

  2. 如果您正在使用Spring-Webflux,并且想要在一个地方生成tradeId并将其添加到Context中,则可以使用WebFilter(文档在这里)来实现。

  3. 然后,您可以使用一些自定义帮助方法从上下文中检索数据,例如Nicolas Portman的示例,或创建自己的自定义日志格式,在其中利用来自Context的数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接