其他分享
首页 > 其他分享> > springboot链路追踪ID

springboot链路追踪ID

作者:互联网

1、实现拦截器,请求开始时候创建MDC值,结束后清理MDC值

2、实现线程池,将MDC上下文从主线程传递给子线程

拦截器:

import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * 拦截器
 *
 * @author 许伟强51189
 * @date 2022/5/25 10:41
 */
public class TraceIdInterceptor implements HandlerInterceptor {

    public static final String UNIQUE_ID = "TRACE_ID";

    public boolean preHandle(@NotNull HttpServletRequest httpServletRequest, @NotNull HttpServletResponse httpServletResponse, @NotNull Object o) {
        MDC.put(UNIQUE_ID, UUID.randomUUID().toString());
        return true;
    }

    public void postHandle(@NotNull HttpServletRequest httpServletRequest, @NotNull HttpServletResponse httpServletResponse, @NotNull Object o, ModelAndView modelAndView) {
    }

    public void afterCompletion(@NotNull HttpServletRequest httpServletRequest, @NotNull HttpServletResponse httpServletResponse, @NotNull Object o, Exception e) {
        MDC.clear();
    }
}

注册拦截器:

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * TraceID的拦截器\生成請求的唯一值
 *
 * @author 许伟强51189
 * @date 2022/5/25 10:41
 */
@Configuration
public class TraceIdInterceptorConfiguration implements WebMvcConfigurer {

    @Value("${spring.traceIdInterceptor.enable:false}")
    private Boolean enable;

    @Value("${spring.traceIdInterceptor.addPathPatterns:/**}")
    private String[] addPathPatterns;

    @Value("${spring.traceIdInterceptor.excludePathPatterns:}")
    private String[] excludePathPatterns;

    @Override
    public void addInterceptors(@NotNull InterceptorRegistry interceptorRegistry) {
        if (!enable) {
            return;
        }
        TraceIdInterceptor myInterceptor = new TraceIdInterceptor();
        interceptorRegistry.addInterceptor(myInterceptor).addPathPatterns(addPathPatterns).excludePathPatterns(excludePathPatterns);
    }
}

线程池:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * MdcThreadPoolConfiguration - 用于链路追踪MDC的线程池\在多线程情况下会将主线程的上下文传递给子线程
 *
 * @author 许伟强51189
 * @date 2022/5/25 16:50
 */
@EnableAsync
@Configuration
public class MdcThreadPoolConfiguration {
    private int corePoolSize = 50;
    private int maxPoolSize = 200;
    private int queueCapacity = 1000;
    private int keepAliveSeconds = 300;

    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setTaskDecorator(new MdcTaskDecorator());
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

上下文传递

/**
 * 任务适配器
 *
 * @author 许伟强51189
 * @version 2.0.0
 * @date 2022/5/25 15:36
 */
public class MdcTaskDecorator implements TaskDecorator {
    /**
     * 使异步线程池获得主线程的上下文
     *
     * @param runnable
     * @return
     */
    @Override
    public Runnable decorate(Runnable runnable) {
        Map<String, String> map = MDC.getCopyOfContextMap();
        return () -> {
            try {
                MDC.setContextMap(map);
                runnable.run();
            } finally {
                MDC.clear();
            }
        };
    }
}

验证可用:

@Async("threadPoolTaskExecutor")
    public void getUserListAsyncThree(int page, int limit, String hash) {
        log.info("getUserListAsyncThree Thread Name:{}", Thread.currentThread().getName());
        System.out.println(MDC.get(TraceIdInterceptor.UNIQUE_ID));
    }

 

 

参考博客:

https://jishuin.proginn.com/p/763bfbd69eeb

标签:NotNull,springboot,MDC,链路,springframework,public,org,import,ID
来源: https://www.cnblogs.com/xuweiqiang/p/16310153.html