分布式追踪库自定义trace id:Spring Sleuth适配自定义请求头方案咨询
Spring 自定义链路ID实现方案
核心实现逻辑
基于原生Spring Sleuth组件改造,仅替换默认B3头部传播规则,保留Sleuth原生的MDC自动注入、跨服务透传、后续采样&上报能力,无需从零自研链路组件。
实现步骤
1. 依赖配置
仅引入Sleuth核心依赖,排除暂时不需要的Zipkin上报相关组件,Maven配置示例:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <!-- 排除Zipkin上报依赖,暂不需要 --> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> </exclusion> </exclusions> </dependency>
2. 自定义头部传播规则
自定义传播器替换默认B3实现,支持x-trace-id等自定义请求头的解析、透传:
import brave.propagation.Propagation; import brave.propagation.TraceContext; import brave.propagation.TraceContextOrSamplingFlags; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Arrays; import java.util.List; import java.util.UUID; @Configuration public class SleuthPropagationConfig { // 自定义链路头名称,可按企业规范调整 public static final String X_TRACE_ID = "x-trace-id"; public static final String X_SPAN_ID = "x-span-id"; public static final String X_PARENT_SPAN_ID = "x-parent-span-id"; public static final List<String> CUSTOM_HEADER_NAMES = Arrays.asList(X_TRACE_ID, X_SPAN_ID, X_PARENT_SPAN_ID); @Bean public Propagation.Factory customPropagationFactory() { return new Propagation.Factory() { @Override public List<String> keys() { return CUSTOM_HEADER_NAMES; } @Override public <R> TraceContext.Injector<R> injector(Propagation.Setter<R, String> setter) { return (traceContext, request) -> { setter.put(request, X_TRACE_ID, traceContext.traceIdString()); setter.put(request, X_SPAN_ID, traceContext.spanIdString()); if (traceContext.parentIdString() != null) { setter.put(request, X_PARENT_SPAN_ID, traceContext.parentIdString()); } }; } @Override public <R> TraceContext.Extractor<R> extractor(Propagation.Getter<R, String> getter) { return request -> { String traceId = getter.get(request, X_TRACE_ID); String spanId = getter.get(request, X_SPAN_ID); // 入站请求无链路ID时自动生成新的链路上下文 if (traceId == null || spanId == null) { return TraceContextOrSamplingFlags.EMPTY; } TraceContext.Builder builder = TraceContext.newBuilder() .traceId(traceId.isBlank() ? generateTraceId() : traceId) .spanId(spanId.isBlank() ? generateSpanId() : spanId); String parentSpanId = getter.get(request, X_PARENT_SPAN_ID); if (parentSpanId != null && !parentSpanId.isBlank()) { builder.parentId(parentSpanId); } return TraceContextOrSamplingFlags.create(builder.build()); }; } }; } // 自定义ID生成规则,可根据企业规范调整 private String generateTraceId() { return UUID.randomUUID().toString().replace("-", ""); } private String generateSpanId() { return UUID.randomUUID().toString().replace("-", "").substring(0, 16); } }
3. 应用配置
在application.yml中启用自定义传播规则,关闭Zipkin上报,默认全量采样(满足当前日志全量采集需求):
spring: sleuth: propagation: # 启用自定义传播器 type: custom # 全量采样,后续接入采集器后可直接调整该参数 sampler: probability: 1.0 zipkin: enabled: false
4. 日志格式配置
在日志框架(以Logback为例)的pattern中添加链路ID字段,自动输出到日志中:
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - traceId:%X{x-trace-id:-} spanId:%X{x-span-id:-} %msg%n"/>
后续接入中心化采集器兼容方案
后续需要部署Zipkin/OpenTelemetry等采集器时,仅需做2处修改,无需调整现有链路逻辑:
- 移除Sleuth依赖中Zipkin的排除规则,引入Zipkin上报依赖
- 修改
application.yml配置:打开spring.zipkin.enabled=true,配置Zipkin上报地址,按需调整spring.sleuth.sampler.probability采样率即可
注意事项
- 跨服务调用透传:Sleuth原生适配RestTemplate、Feign、Spring Cloud Gateway、Dubbo等组件,自定义头会自动透传,无需额外开发
- 异步场景透传:使用Spring提供的
ThreadPoolTaskExecutor等托管线程池,Sleuth会自动完成MDC上下文透传,无需手动处理 - 避免手动修改MDC中的
x-trace-id、x-span-id字段,防止和Sleuth自动注入逻辑冲突
内容的提问来源于stack exchange,提问作者Srini M
相关产品推荐
相关产品推荐

