1

我们使用 MDC 记录所有带有 session Id 的事务,但有时它会附加错误的 sessiond

我正在筛选过滤器中的 sessionId

MDC.put("sessionId", request.getSession().getId());

日志输出

2015-01-24 23:13:04,857 INFO [STDOUT] (http-0.0.0.0-8090-28) [LOGBACK] 23:13:04.857 [INFO ] 371691C0B3B4481E9589BDE0C24F54C8 [Inbound Message][ID:319526][Address:http://195.233.91.82:8090/myacct/activate/updateConsent][Http-Method:POST][Content-Type:application/json; charset=UTF-8][Headers:{cookie=[JSESSIONID=371691C0B3B4481E9589BDE0C24F54C8;.....
2015-01-24 23:13:05,242 INFO [STDOUT] (http-0.0.0.0-8090-28) [LOGBACK] 23:13:05.242 [INFO ] 1434BC692D5059660EA0F8B36B143064 [Outbound Message][ID:319526][Response-Code:200][Content-Type:application/json;charset=utf-8].......

正如您所看到的,恢复的 sessionId 请求何时正确,以及何时记录响应时附加了错误的 sessionId,但两个日志的线程相同。

根据 MDC “MDC 是按线程管理的”

我做错了什么吗?

4

1 回答 1

3

引用来源:

https://blog.trifork.com/2013/06/06/adding-user-info-to-log-entries-in-a-multi-user-app-using-mapped-diagnostic-context/

MDC 基于 ThreadLocal 的后果

在重新使用线程来处理另一个请求之前,您应该删除您放入其中的条目,以免线程的下一个用户无意中拾取它们。通常最好在 finally 子句中执行此操作,如上例所示,这样即使在引发异常的情况下也会进行清理。

子线程会自动将 MDC 内容传播到其他线程(更新:对于从 1.1.5 版开始的 Logback,这不再适用),但当您使用从线程池等获取的线程时则不会。这意味着当您运行一些异步任务时,您会丢失 MDC 信息。

如果您希望 MDC 内容可从工作线程获得,请确保在运行任务之前将 MDC 内容传播到这些线程。SLF4J 的 MDC 有一个用于此特定目的的 getCopyOfContextMap() 方法。一种可能的方法是使用专用的 Runnable 子类:

于 2018-08-07T14:47:47.167 回答