Spring Boot接入链路追踪(Micrometer Tracing+Zipkin) 一
分布式追踪集成:自动透传 TraceID 1. 使用 Micrometer Tracing(Spring Boot 3+ 推荐)
在 Spring Boot 3.x + Spring Cloud 2022+(如 2023.0.x)中,
Spring Cloud Sleuth 已被弃用,官方推荐使用 Micrometer Tracing(基于 Brave 或 OpenTelemetry)来实现分布式追踪,包括自动透传 traceId 和 spanId,并将其注入到日志的 MDC 中,供日志系统(如 ELK、Loki)使用。
✅ 一、依赖管理(更完整的配置)
Maven (pom.xml)
xml
<?xml version="1.0" encoding="UTF-8"?> <project><properties><micrometer-tracing.version>1.2.0</micrometer-tracing.version><zipkin-reporter.version>2.16.3</zipkin-reporter.version></properties><dependencies><!-- Micrometer Tracing with Brave --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bridge-brave</artifactId></dependency><!-- Brave 传播器 --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing</artifactId></dependency><!-- Zipkin 报告器 --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-reporter-brave</artifactId><version>${zipkin-reporter.version}</version></dependency><!-- HTTP 发送器 --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-sender-okhttp3</artifactId><version>${zipkin-reporter.version}</version></dependency><!-- 日志结构化 --><dependency><groupId>net.logstash.logback</groupId><artifactId>logstash-logback-encoder</artifactId><version>7.4</version></dependency><!-- Web 客户端支持(必须,用于 HTTP 调用追踪) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Actuator(必须,用于追踪端点) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bom</artifactId><version>${micrometer-tracing.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement> </project>
Gradle (build.gradle)
gradle
ext {micrometerTracingVersion = '1.2.0'zipkinReporterVersion = '2.16.3' }dependencies {// Micrometer Tracingimplementation 'io.micrometer:micrometer-tracing-bridge-brave'implementation 'io.micrometer:micrometer-tracing'// Zipkinimplementation "io.zipkin.reporter2:zipkin-reporter-brave:${zipkinReporterVersion}"implementation "io.zipkin.reporter2:zipkin-sender-okhttp3:${zipkinReporterVersion}"// 日志implementation 'net.logstash.logback:logstash-logback-encoder:7.4'// Spring Bootimplementation 'org.springframework.boot:spring-boot-starter-web'implementation 'org.springframework.boot:spring-boot-starter-actuator' }dependencyManagement {imports {mavenBom "io.micrometer:micrometer-tracing-bom:${micrometerTracingVersion}"} }
✅ 二、详细配置(application.yml)
yaml
spring:application:name: order-service# Sleuth 兼容配置(可选)sleuth:enabled: false # 明确禁用 Sleuth# Micrometer Tracing 配置 management:tracing:enabled: truesampling:probability: 1.0 # 采样率:1.0=100%, 0.1=10%# 传播类型配置propagation:type: W3C # 支持:W3C, B3, B3_MULTI# Brave 特定配置brave:sampler:rate: 10000 # 每秒最大采样数# Actuator 端点endpoints:web:exposure:include: health,metrics,info,tracecontext# Zipkin 配置(可选) zipkin:base-url: http://localhost:9411enabled: truesender:type: web # 使用 HTTP 发送# 日志配置 logging:pattern:level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"level:io.micrometer.tracing: DEBUG # 调试时可开启
✅ 三、增强的 Logback 配置
logback-spring.xml
xml
<?xml version="1.0" encoding="UTF-8"?> <configuration><include resource="org/springframework/boot/logging/logback/defaults.xml"/><!-- JSON 格式输出 --><appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"><providers><timestamp><timeZone>UTC</timeZone></timestamp><logLevel/><loggerName/><message/><pattern><pattern>{"service": "${spring.application.name:-unknown}"}</pattern></pattern><mdc><!-- 包含所有 MDC 字段 --><includeMdcKeyName>traceId</includeMdcKeyName><includeMdcKeyName>spanId</includeMdcKeyName><includeMdcKeyName>parentId</includeMdcKeyName><includeMdcKeyName>service.name</includeMdcKeyName></mdc><threadName/><stackTrace><throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter"><maxDepthPerThrowable>30</maxDepthPerThrowable><maxLength>2048</maxLength><shortenedClassNameLength>20</shortenedClassNameLength><rootCauseFirst>true</rootCauseFirst></throwableConverter></stackTrace></providers></encoder></appender><!-- 传统格式输出(开发环境) --><appender name="PLAIN_CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId:-},%X{spanId:-}] %logger{36} - %msg%n</pattern></encoder></appender><!-- 根据 profile 选择输出格式 --><springProfile name="dev | local"><root level="INFO"><appender-ref ref="PLAIN_CONSOLE"/></root></springProfile><springProfile name="!dev & !local"><root level="INFO"><appender-ref ref="JSON_CONSOLE"/></root></springProfile><!-- 特定包日志级别 --><logger name="com.yourcompany" level="DEBUG"/><logger name="org.springframework.web" level="INFO"/><logger name="io.micrometer.tracing" level="INFO"/> </configuration>
✅ 四、验证和测试控制器
java
@RestController @Slf4j public class TraceDemoController {private final RestTemplate restTemplate;private final Tracer tracer;public TraceDemoController(RestTemplateBuilder restTemplateBuilder, Tracer tracer) {this.restTemplate = restTemplateBuilder.build();this.tracer = tracer;}@GetMapping("/demo")public String demoTrace() {log.info("收到请求 - 开始处理");// 当前追踪信息Span currentSpan = tracer.currentSpan();if (currentSpan != null) {log.info("TraceId: {}, SpanId: {}", currentSpan.context().traceId(),currentSpan.context().spanId());}// 模拟业务处理processBusiness();log.info("请求处理完成");return "Trace ID: " + (currentSpan != null ? currentSpan.context().traceId() : "null");}@GetMapping("/call-downstream")public String callDownstream() {log.info("调用下游服务开始");// 自动携带追踪头调用下游服务String result = restTemplate.getForObject("http://localhost:8081/demo", String.class);log.info("下游服务调用完成: {}", result);return "Called downstream: " + result;}private void processBusiness() {log.debug("处理业务逻辑...");// 业务代码} }
✅ 五、配置类(确保正确配置)
java
@Configuration public class TracingConfig {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {return builder.build();}@Beanpublic Sampler alwaysSampler() {return Sampler.ALWAYS_SAMPLE;} }
✅ 六、异步任务中的追踪处理
java
@Service @Slf4j public class AsyncService {private final Tracer tracer;private final ObservationRegistry observationRegistry;public AsyncService(Tracer tracer, ObservationRegistry observationRegistry) {this.tracer = tracer;this.observationRegistry = observationRegistry;}// 方法1:使用 Observation(推荐)@Asyncpublic CompletableFuture<String> processAsync(String data) {return Observation.createNotStarted("async-process", observationRegistry).observe(() -> {log.info("异步处理数据: {}", data);// 模拟处理try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}log.info("异步处理完成");return CompletableFuture.completedFuture("processed: " + data);});}// 方法2:手动传播上下文@Asyncpublic void manualAsyncProcess() {// 获取当前上下文Span currentSpan = tracer.currentSpan();if (currentSpan != null) {// 在新的线程中手动设置上下文try (Tracer.SpanInScope scope = tracer.withSpan(currentSpan)) {log.info("手动传播的异步任务");// 业务逻辑}} else {log.info("没有追踪上下文的异步任务");}} }
✅ 七、Feign Client 集成
java
@FeignClient(name = "payment-service", url = "http://localhost:8082") public interface PaymentClient {@GetMapping("/payment")String processPayment(); }// 自动支持追踪,无需额外配置
✅ 八、常见问题解决方案
1. 自定义 HTTP 客户端追踪
java
@Bean public RestTemplate tracedRestTemplate() {RestTemplate restTemplate = new RestTemplate();// 添加追踪拦截器List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();interceptors.add(new TracingClientHttpRequestInterceptor(tracer));restTemplate.setInterceptors(interceptors);return restTemplate; }
2. 手动记录 Span
java
@Autowired private Tracer tracer;public void manualSpan() {Span span = tracer.nextSpan().name("custom-operation").start();try (Tracer.SpanInScope scope = tracer.withSpan(span)) {span.event("操作开始");log.info("执行自定义操作");// 业务逻辑span.tag("result", "success");} catch (Exception e) {span.tag("result", "error");span.error(e);throw e;} finally {span.end();} }
✅ 九、健康检查端点
访问 http://localhost:8080/actuator/tracecontext
查看当前追踪上下文:
json
{"traceId": "a1b2c3d4e5f6a7b8","spanId": "c9d0e1f2a3b4c5d6","parentId": null,"sampled": true }
✅ 十、完整的日志输出示例
json
{"@timestamp": "2024-01-15T10:30:00.123Z","level": "INFO","logger": "com.example.TraceDemoController","message": "收到请求 - 开始处理","service": "order-service","traceId": "a1b2c3d4e5f6a7b8","spanId": "c9d0e1f2a3b4c5d6","thread": "http-nio-8080-exec-1" }
这个方案提供了:
✅ 完整的依赖配置
✅ 详细的配置文件
✅ 多种日志格式支持
✅ 异步任务追踪
✅ 常见问题解决方案
✅ 验证和测试方法