第八章节介绍MDC对象,它的内容如下:
- MDC对象的概念,以及它的使用。
- MDC对象的应用场景。本文省略,参考原著内容。
1、概念
MDC的全称是Mapped Diagnostic Context。原著中对它的定义如下:
To uniquely stamp each request the user puts contextual information into the MDC,the abbreviation of Mapped Diagnostic Context
理解这段定义之前,先举个示例。
在Web应用中,当用户登录之后,会随之创建一个Session对象,之后用户的所有请求都与之绑定,session对象就扮演着作用域的角色,它为每一个用户提供一个私有的作用域,彼此之间相互独立。在session作用域中存放的变量,可以在相同用户的不同请求中获取。
Session的作用是唯一标识一个用户。
MDC与Session扮演的角色是一样的,它的作用是在多线程,多用户的场景下,唯一标识一个请求。粒度比session更细一些。
在每一个线程中,都会有一个MDC对象,它可以保存上下文信息,这些信息可以在当前上下文中随意获取,当线程销毁之后,MDC对象也被回收,所有变量都无效。
在每一个日志请求中,可以通过添加一些唯一性的上下文信息,用于标识日志请求等等。例如在Web请求时,将用户的ID,请求的URL路径等信息放入到MDC中。并在每一条日志信息中输出这些上下文信息。
每个日志请求中不是包含线程信息吗?为什么需要MDC?
原著中的回答是:
The thread name can cause confusion if the server side technology recycles threads, In that case, it may be hard to determine the boundaries of each request, that is, when a given thread finishes servicing a request and when it begins servicing the next, Because the MDC is under the control of the developer, MDC attempts do not suffer from this problem.
这段话意思是线程回收之后,在次创建时线程名称可能会重复,而MDC伴随着线程的生命周期,每一个线程中的MDC对象都是不同的。
MDC与线程之间的关系是一对一的,它伴随着线程的生命周期,而在绝大多数情况下,每个线程对应一次用户请求,用户请求又可以找到对应的用户。有的线程甚至可以直接与用户建立关联,例如在建立TCP,HTTP连接时。
2、MDC对象
MDC对象使用起来和Map差不多,保存的是key-value的键值对。代码如下:
public class MDC{ public static void put(String key,String value); public static String get(String key); public static void remove(String key); public static void clear }
它的使用步骤很简单:
- 在Java程序中,调用MDC的put方法,之后所有的日志请求都可以访问到。
- 在配置文件中,在日志格式中配置%mdc{key}。
- 在终端中的日志信息中即可看到key对应的value值。
它的应用场景是在多用户,多线程的情况下,为日志信息添加用户标识变量或者其他唯一性变量,方便分析请求流程。
在并发量比较小的情况下,用户的同一次请求的日志信息大部分是连贯的,或许中间会夹杂少量其他用户请求的日志信息,此时配置MDC的意义不是很大。
至此本篇内容结束,原著链接:http://logback.qos.ch/manual/mdc.html