ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

springboot链路追踪ID

2022-05-25 18:03:57  阅读:150  来源: 互联网

标签:NotNull springboot MDC 链路 springframework public org import 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有