Log4j的MDC机制如何在线程池中使⽤
问题1:我们希望当有⼀个请求时,全部相应后台⽇志增加⼀个统⼀的全局requestId ⽅便⽇志搜集和处理:
我们可以使⽤sl4j MDC机制。
问题2:sl4j MDC机制原理:
通常⽤于保存线程本地的“诊断数据”然后有⽇志组件打印,其内部时基于threadLocal实现
问题3:MDC如何使⽤:
步骤 1 在或者统⼀的⽅法⼊⼝加上
MDC.put(“REQUEST_ID”,xxx);
步骤 2 改动log4j⽇志格式,增加该字段 REQUEST_ID ⽐如下⾯例⼦即可:
改前:%-d{yyyy-MM-dd HH:mm:ss,SSS} [%p] % %m%n
改后:%-d{yyyy-MM-dd HH:mm:ss,SSS} [%p] %X{REQUEST_ID} %m%n
log4j2不打印日志问题4:但对于多线程情况,⽐如主线程创建了⼀些⼦线程,那么这些⼦线程能不能⾃动带上MDC所赋的值呢?
答案是可能会出问题。
我们看官⽅⽂档说明:
=========================================================================================
Implementation details
The Stack and the Map are managed per thread and are based on ThreadLocal by default. The Map can be configured to use an InheritableThreadLocal by setting system property
log4j2.isThreadContextMapInheritable to true. When configured this way, the contents of the Map will be passed to child threads. However, as discussed in the Executors class and in other cases where thread pooling is utilized, the ThreadContext may not always be automatically passed to worker threads. In those cases the pooling mechanism should provide a means for doing so. The getContext() and cloneStack() methods can be used to obtain copies of the Map and Stack respectively.
Note that all methods of the ThreadContext class are static.
翻译过来 ==================================================================================
实施细节
堆栈和映射是按线程管理的,默认情况下基于ThreadLocal。通过将系统属性log4j2.isThreadContextMapInheritable设置为true,可以将Map配置为使⽤InheritableThreadLocal。通过这种⽅式配置后,映射的内容将传递给⼦线程。但是,如在Executors类中讨论的以及在其他使⽤线程池的情况下,ThreadContext可能不会始终⾃动传递给⼯作线程。在这些情况下,池化机制应提供这样做的⼿段。 getContext()和cloneStack()⽅法可分别⽤于获取Map和Stack的副本。
请注意,ThreadContext类的所有⽅法都是静态的。
=========================================================================================
测试使⽤的是线程池,跑了⼀次发现线程池中的⼦线程会把MDC的值打印出来,并且和主线程MDC值⼀致,与官⽅⽂档⽭盾,经过分析发现:
⽤线程池的时候会有问题的,测试ok,是因为⼯作线程第⼀次的时候是当前的线程创建的,如果复⽤的话会出现问题的,果然把线程池⼤⼩改成1,
然后多调⼏次就发现⼦线程中的MDC值永远是第⼀次创建时的值不会变,
所以确认官⽅⽂档是对的:主线程中设置的MDC数据,在其⼦线程(多线程池)中是⽆法获取的。
下⾯就来介绍如何解决这个问题。
在⼦线程类经过如上代码改动,则主线程中的MDC值会成功的⾃动传递给该⼦线程,亲测有效。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论