Tag: mdc

如何使用线程池的MDC?

在我们的软件中,我们广泛使用MDC来跟踪networking请求的会话ID和用户名等内容。 这在原始线程中运行正常。 但是,有很多事情需要在后台处理。 为此,我们使用java.concurrent.ThreadPoolExecutor和java.util.Timer类以及一些自卷asynchronous执行服务。 所有这些服务pipe理他们自己的线程池。 这就是Logback的手册在这样的环境中使用MDC的说法: 映射的诊断上下文的副本不能始终由启动线程的工作线程inheritance。 当java.util.concurrent.Executors用于线程pipe理时就是这种情况。 例如,newCachedThreadPool方法创build一个ThreadPoolExecutor并像其他线程池代码一样,它具有复杂的线程创build逻辑。 在这种情况下,build议在向执行程序提交任务之前,在原始(主)线程上调用MDC.getCopyOfContextMap()。 当任务运行时,作为其第一个操作,它应调用MDC.setContextMapValues()将原始MDC值的存储副本与新的Executorpipe理线程相关联。 这样可以,但是忘记添加这些电话是很容易的,而且要等到为时已晚,还没有简单的方法来识别问题。 Log4j的唯一标志就是在日志中丢失了MDC信息,而在Logback中,您会得到陈旧的MDC信息(因为在步骤池中的线程从在其上运行的第一个任务inheritance其MDC)。 两者都是生产系统中的严重问题。 我没有看到我们的情况有任何特殊之处,但我在网上找不到这个问题。 显然,这不是很多人碰到的事情,所以一定要有办法避免。 我们在这里做错了什么?