You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SpringBoot微服务中实现用于链路追踪的req id(请求ID)

Spring Boot 微服务请求链路唯一标识透传实现方案

该需求核心是实现全链路TraceId(请求唯一标识)的透传,优先级为客户端传入标识 > 服务端自动生成标识,最终通过日志关联全链路处理信息。

1. 核心实现步骤

  • 定义链路上下文持有类
    基于ThreadLocal实现线程级别的TraceId存储,避免多请求数据混乱,用完需主动清理避免内存泄漏,示例代码如下:

    public class TraceContextHolder {
        private static final ThreadLocal<String> TRACE_ID_HOLDER = new ThreadLocal<>();
    
        public static void setTraceId(String traceId) {
            TRACE_ID_HOLDER.set(traceId);
        }
    
        public static String getTraceId() {
            return TRACE_ID_HOLDER.get();
        }
    
        public static void clear() {
            TRACE_ID_HOLDER.remove();
        }
    }
    
  • 编写请求拦截器生成/获取TraceId
    实现Spring的HandlerInterceptor,在请求进入时优先提取客户端传入的标识,无传入则自动生成,同时存入上下文和SLF4J的MDC(映射诊断上下文)方便日志打印,请求结束后清理上下文:

    @Component
    public class TraceInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 优先从请求头取,其次从查询参数取客户端传入的TraceId
            String traceId = request.getHeader("X-Trace-Id");
            if (traceId == null || traceId.isBlank()) {
                traceId = request.getParameter("traceId");
            }
            // 无传入则自动生成UUID作为TraceId
            if (traceId == null || traceId.isBlank()) {
                traceId = UUID.randomUUID().toString().replace("-", "");
            }
            TraceContextHolder.setTraceId(traceId);
            MDC.put("traceId", traceId);
            return true;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 请求结束清理上下文,避免内存泄漏
            TraceContextHolder.clear();
            MDC.remove("traceId");
        }
    }
    

    之后将该拦截器注册到Spring MVC配置中即可生效。

  • 日志格式配置
    修改日志框架(如Logback)的输出格式,增加%X{traceId}占位符,所有日志就会自动携带当前请求的TraceId,示例格式配置:

    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - traceId:%X{traceId} - %msg%n</pattern>
    
  • 跨组件/跨服务透传适配

    • 若使用Feign做跨服务调用:自定义RequestInterceptor将TraceId放入下游请求头
      @Component
      public class FeignTraceInterceptor implements RequestInterceptor {
          @Override
          public void apply(RequestTemplate template) {
              String traceId = TraceContextHolder.getTraceId();
              if (traceId != null) {
                  template.header("X-Trace-Id", traceId);
              }
          }
      }
      
    • 若使用异步线程/@Async注解:自定义线程池装饰器,将父线程的TraceId传递到子线程中
    • 若使用消息队列:发送消息时将TraceId放入消息属性,消费时取出存入当前线程的上下文和MDC中

2. 排查使用方式

请求出错后,直接根据返回的TraceId或者用户提供的传入TraceId,检索所有服务的日志,即可拿到该请求在全链路各个节点的完整处理日志,快速定位异常节点和原因。

如果不想从零实现全链路逻辑,也可以直接使用Spring官方提供的链路追踪组件,基于上述逻辑做了封装,可自行配置透传规则满足需求。


内容的提问来源于stack exchange,提问作者Ayush Goyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 15:39:01