MDC使用手册精讲

本文介绍了在高并发场景下,如何使用MDC(MappedDiagnosticContext)作为全局唯一标识跟踪请求链路,通过在请求头添加UUID并在日志中记录,实现实时定位问题。同时,文章详细展示了MDC在logback中的实现方式,以及如何配合日志收集工具如ELK或LPG进行统一的日志管理。

MDC

背景: 线上排查问题时,请求在多个微服务之间进行调用,并发量较大的情况下,想跟踪某一个请求的链路,是需要花费一些时间才能梳理出来,而且还依赖于你的业务字段。而我们需要的是快速定位,快速纠错,因此就需要一个唯一的全局标识用来识别并跟踪这个请求。

想法: 一个唯一全局标识,并且还能在上下游之间进行传递,那可以对这个请求 request 做些特殊操作,我们可以在请求头上添加这个全局标识,比如使用UUID,在进入每一个微服务之前进行拦截 (filter/intercept),获取这个UUID并设置到当前线程中。输出日志时,就把这个UUID也输出到日志中,这样便可以快速识别并定位。如果在业务代码中使用了多线程,也应该记录,这就需要使用到本次介绍的重点内容:MDC

介绍: MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。MDC 中包含的内容可以被同一线程中执行的代码所访问,当前线程的子线程也会继承其父线程中的 MDC 的内容。

我们日志用的是 slf4j + logback,看看 slf4j-api 包结构,发现了一个 spi ,是不是很熟悉,虽然这个 spi 只是一个包名,但是实质是一样的

在这里插入图片描述

slf4j-api 包下有一个 MDCAdapter接口,如下

public interface MDCAdapter {
   
   
  //通过k-v设置  
  public void put(String key, String val);

  public String get(String key);

  public void remove(String key);

  public void clear();

  public Map getCopyOfContextMap();

  public void setContextMap(Map contextMap);
}

由于使用的是logback日志,对应的logback也提供了MDCAdapter接口的实现,如下

在这里插入图片描述

我们看看logback里面是如何实现 MDCAdapter 接口的。发现是基于InheritableThreadLocal 来实现的,这个就很好的处理的父子线程的问题,也就是可以trace线程池

public final class LogbackMDCAdapter implements MDCAdapter {
   
   

  final InheritableThreadLocal<Map<String, String>> copyOnInheritThreadLocal = new InheritableThreadLocal<Map<String, String>>();

  private static final int WRITE_OPERATION = 1;
  private static final int READ_OPERATION = 2;

  // keeps track of the last operation performed
  final ThreadLocal<Integer> lastOperation = new ThreadLocal
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗罗的1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值