Spring Cloud Trace 链路实现

基于 Spring Boot 4.x / Spring Cloud Alibaba 2025.1.x,同时对比 Spring Boot 3.5 的关键差异。

项目地址:github.com/javahongxi/...

本项目集成了 OpenTelemetry + Micrometer Tracing 作为分布式链路追踪方案,覆盖 HTTP、Feign、WebClient、Dubbo RPC 等多种调用场景。以下从依赖引入、配置、传播策略三个维度展开说明,并标注 Spring Boot 3 与 4 之间的区别。


1. 依赖引入

1.1 main 分支(Spring Boot 4.0)

所有运行时模块统一引入 spring-boot-starter-opentelemetry

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-opentelemetry</artifactId>
</dependency>

该 starter 是 Spring Boot 4.0 新增的一站式依赖,内部包含完整的分层模块:

  • spring-boot-opentelemetry --- 创建 OpenTelemetry Bean(底层核心)
  • spring-boot-micrometer-tracing-opentelemetry --- 基于 OpenTelemetry 创建 Tracer Bean
  • micrometer-tracing-bridge-otel --- OTel 桥接实现
  • opentelemetry-exporter-otlp --- OTLP 数据导出器

1.2 springboot3 分支(Spring Boot 3.5)

3.5 分支中,tracing 自动配置仍包含在 spring-boot-starter-actuator 内,只需额外引入 bridge:

xml 复制代码
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>

1.3 为什么 4.0 要换?

Spring Boot 4.0 将链路追踪自动配置从 spring-boot-actuator-autoconfigure 中彻底拆分出来。如果 4.0 项目仍然只引入 micrometer-tracing-bridge-otel,启动时会依次报错:

  1. required a bean of type 'io.opentelemetry.api.OpenTelemetry' that could not be found --- 缺少 spring-boot-opentelemetry
  2. required a bean of type 'io.micrometer.tracing.Tracer' that could not be found --- 缺少 spring-boot-micrometer-tracing-opentelemetry

结论 :升级 4.0 后,用 spring-boot-starter-opentelemetry 替换原来的 micrometer-tracing-bridge-otel,避免分层依赖遗漏。


2. 配置

2.1 采样率

所有模块统一配置全量采样,开发环境完整记录每一次调用链:

yaml 复制代码
management:
  tracing:
    sampling:
      probability: 1.0

2.2 OTLP Metrics 导出关闭(4.0 新增)

spring-boot-starter-opentelemetry 内置了 micrometer-registry-otlp,默认会向 http://localhost:4318/v1/metrics 推送 Metrics。本地开发环境没有 OTLP Collector 时会报 Connection refused,因此所有模块都添加了:

yaml 复制代码
management:
  otlp:
    metrics:
      export:
        enabled: false

3.5 分支无需此配置 ,因为 micrometer-tracing-bridge-otel 不包含 Metrics 导出模块。

2.3 Dubbo 模块额外配置

Dubbo provider 和 consumer 均启用 Dubbo 内置 tracing 支持:

yaml 复制代码
dubbo:
  tracing:
    enabled: true

同时,集成了 Dubbo 的模块(consumer、consumer-reactive、provider-dubbo)需排除 Dubbo 自带的 OpenTelemetry 自动配置,避免 Bean 定义冲突:

java 复制代码
@SpringBootApplication(exclude = {
    org.apache.dubbo.spring.boot.autoconfigure.observability.otel.OpenTelemetryAutoConfiguration.class
})

原因是 Dubbo 的 OpenTelemetryAutoConfiguration 与 Spring Boot 4.0 的 spring-boot-starter-opentelemetry 都定义了 otelSpanProcessor Bean,默认不允许覆盖时会启动失败。3.5 分支中 Dubbo 的 OTel AutoConfig 与 micrometer-tracing-bridge-otel 不冲突,无需排除。


3. 各链路的 Trace 传播策略

项目使用 W3C Trace Context 协议,通过 traceparent header(格式 00-<traceId>-<spanId>-01)在跨服务间传播追踪上下文。不同调用方式的传播策略不同:

3.1 Gateway 层 --- 自动传播

Spring Cloud Gateway 基于 WebFlux,引入 spring-boot-starter-opentelemetry 后,Gateway 会自动从入站请求提取 traceparent,并在路由到下游服务时注入该 header。Gateway → Consumer 这段的 trace 传播是框架自动完成的。

3.2 Consumer → Provider(RestTemplate) --- 自动传播

Consumer 模块通过 RestTemplateBuilder 创建 @LoadBalanced 的 RestTemplate:

java 复制代码
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

Spring Boot 的 RestTemplateBuilder 会自动注册 tracing 拦截器,将当前 Span 的 traceparent 注入到出站 HTTP 请求中。

注意 :4.0 中 RestTemplateBuilder 的包路径从 org.springframework.boot.web.client 变更为 org.springframework.boot.restclient,import 需要同步修改。

3.3 Consumer → Provider(Feign) --- 手动传播

OpenFeign 不会自动传播 trace context,需要手动注册 RequestInterceptor

java 复制代码
@Bean
public RequestInterceptor feignTracingInterceptor(Tracer tracer) {
    return template -> {
        Span currentSpan = tracer.currentSpan();
        if (currentSpan != null) {
            String traceparent = String.format("00-%s-%s-01",
                    currentSpan.context().traceId(),
                    currentSpan.context().spanId());
            template.header("traceparent", traceparent);
        }
    };
}

Tracer 获取当前 Span,手动拼接 W3C traceparent 格式并注入到 Feign 请求的 header 中。这段代码在 3.5 和 4.0 分支中完全一致。

3.4 Consumer Reactive → Provider Reactive(WebClient) --- 手动传播

WebFlux 下 WebClient 的 trace 自动传播在 Spring Boot 3.5+ 存在兼容性问题,因此采用手动方式:

java 复制代码
@RequestMapping("/hi")
public Mono<String> hi(String name,
        @RequestHeader(value = "traceparent", required = false) String traceparent) {
    return webClient
            .get()
            .uri("/hello?name={name}", name)
            .headers(h -> {
                if (traceparent != null) {
                    h.set("traceparent", traceparent);
                }
            })
            .retrieve()
            .bodyToMono(String.class);
}

从入站请求的 @RequestHeader("traceparent") 提取上游传来的 traceparent,显式注入到出站请求。

同时,在 ReactiveConsumerApplication 启动时调用 Hooks.enableAutomaticContextPropagation() 确保 Reactor 上下文在异步链中正确传播。

3.5 Consumer → Provider Dubbo(Dubbo RPC) --- 配置启用

Dubbo RPC 不走 HTTP,无法自动传播 HTTP header。项目通过 dubbo.tracing.enabled: true 启用 Dubbo 内置的 tracing 支持,由 Dubbo 框架负责通过 RPC Attachment 机制传播 trace context。

Provider Dubbo 的 REST 接口还暴露了 /api/trace 端点,通过 @Param(value="traceparent", type=ParamType.Header) 直接从 HTTP Header 中读取 traceparent,用于验证网关路由后 trace 上下文是否完整传递。


4. Trace 传播总览

scss 复制代码
用户请求
  │  traceparent (由第一个服务生成)
  ▼
Gateway ───────────────────────────────── 自动传播 (Spring Cloud Gateway tracing filter)
  │
  ├──▶ Consumer (port:8766)
  │      ├──▶ Provider       via RestTemplate  → 自动传播 (RestTemplateBuilder tracing 拦截器)
  │      ├──▶ Provider       via Feign         → 手动传播 (RequestInterceptor + Tracer)
  │      └──▶ Provider Dubbo via Dubbo RPC     → 配置启用 (dubbo.tracing.enabled)
  │
  ├──▶ Consumer Reactive (port:8763)
  │      ├──▶ Provider Reactive via WebClient  → 手动传播 (header 显式注入)
  │      └──▶ Provider Dubbo  via Dubbo RPC    → 配置启用 (dubbo.tracing.enabled)
  │
  └──▶ Dubbo REST (port:50051)
传播方式 自动/手动 原因
Gateway 路由 自动 Spring Cloud Gateway 内置 tracing filter
RestTemplate 自动 RestTemplateBuilder 自动注册 tracing 拦截器
Feign 手动 OpenFeign 不自动传播 trace context,需自定义 RequestInterceptor
WebClient 手动 WebFlux 下自动传播不可靠,手动从入站 header 提取并注入
Dubbo RPC 配置启用 通过 dubbo.tracing.enabled + RPC Attachment 机制

5. 日志可观测性

引入的spring-boot-starter-opentelemetry会自动将logging pattern设定为会输出traceId-spanId的整齐格式日志。另外,为了比较gateway传递过来的trace和当前服务的trace是否一致,在当前服务手动输出了traceparent, 可以看到 Controller 的接口方法通过 @RequestHeader(value = "traceparent", required = false) 接收并打印 traceparent:

java 复制代码
@RequestMapping("/hi")
public String hi(String name,
        @RequestHeader(value = "traceparent", required = false) String traceparent) {
    log.info("traceparent: {}", traceparent);
    // ...
}

如果想可视化, 可配合 Zipkin 等可视化系统,可以通过 traceId 串联完整的调用链。


6. Spring Boot 3 vs 4 关键差异速查

变更类别 Spring Boot 3.5 (springboot3 分支) Spring Boot 4.0 (main 分支)
Tracing 依赖 io.micrometer:micrometer-tracing-bridge-otel spring-boot-starter-opentelemetry
Web Starter spring-boot-starter-web spring-boot-starter-webmvc + spring-boot-starter-restclient
RestTemplateBuilder 包 o.s.boot.web.client.RestTemplateBuilder o.s.boot.restclient.RestTemplateBuilder
OTLP Metrics 不含此模块,无需关闭 内置 micrometer-registry-otlp,需配置 management.otlp.metrics.export.enabled: false
Dubbo OTel 冲突 不冲突,无需排除 需排除 Dubbo OpenTelemetryAutoConfiguration
Protobuf 版本 无冲突 需显式指定 protobuf-java:4.34.1 解决 OTel + Dubbo 版本冲突

Spring Cloud 版本对应:2025.0.0(对应 SB 3.5)→ 2025.1.0(对应 SB 4.0),Spring Cloud Alibaba 版本:2025.0.0.02025.1.0.0

相关推荐
海梨花1 小时前
腾讯面试高频算法题
java·算法·面试
于先生吖1 小时前
Java消息队列优化抢单逻辑,同城搬家拉货多场景业务数据库架构设计
java·开发语言·数据库架构
小谢小哥1 小时前
68-持续集成详解
java·后端·架构
用户925807911481 小时前
redission原理
java·后端
小旭95271 小时前
Spring Cloud 集成分布式日志 ELK+Swagger 接口文档实战
java·分布式·后端·elk·spring cloud
屋外雨大,惊蛰出没1 小时前
spring boot+mybatis开发基础复习
java·spring boot·后端
这个DBA有点耶1 小时前
死锁排查进阶:从日志到根因的完整分析链
java·开发语言·数据库·sql·运维开发·学习方法·dba
JAVA9652 小时前
JAVA面试-并发篇 06-ReentrantLock如何实现公平锁的以及可重入吗
java·开发语言·面试