SpringCloud 核心组件解析:服务链路追踪

SpringCloud 核心组件解析:服务链路追踪

技术栈 :Spring Boot 3.2.0 + Spring Cloud 2023.0.0 + Micrometer Tracing + Zipkin

已不维护:Spring Cloud Sleuth → 替代用 Micrometer Tracing


5.1 是什么 --- 链路追踪的核心概念

5.1.1 生活化类比:快递追踪

你在淘宝买了 3 件商品,想知道它们到哪了:

复制代码
快递单号 SF1234567890(Trace ID)
├── [扫描点 A] 北京分拣中心 12:00 → 12:05 (Span 1)
│   └── [扫描点 B] 北京→上海 运输 12:05 → 18:00 (Span 2)
│       └── [扫描点 C] 上海配送站 → 签收 18:30 (Span 3)
  • Trace ID = 快递单号:贯穿整个流程的唯一标识
  • Span = 扫描记录:每个环节的处理记录(时间、地点、操作)
  • Parent Span → Child Span:表达了调用层级关系

5.1.2 技术定义

在微服务中,一个用户请求可能经过 N 个服务。链路追踪就是给每个请求分配一个全局唯一 ID,记录它经过的每个服务及耗时。

复制代码
用户 → Order Service (Span A, parent=null)
          │ HTTP 调用
          ├→ Payment Service (Span B, parent=Span A)
          │        │ Feign 调用
          │        └→ Account Service (Span C, parent=Span B)
          │
          └→ Inventory Service (Span D, parent=Span A)

Trace ID: 5f7a3b2c...  贯穿整棵树
Span ID:  A/B/C/D...    每个节点一个 ID

5.2 为什么 --- 没有链路追踪的痛点

5.2.1 场景

线上用户反馈"下单等了 10 秒才成功",已知调用链:Nginx → Gateway → Order → Payment → Account。

复制代码
❓ 到底哪个环节慢了?
❓ 是数据库慢还是网络慢?
❓ 10s 里各环节分别占多少?
❓ 有没有哪个服务报错了?

没有链路追踪,排查方式 = 挨个服务查日志 + 靠时间戳对着拼。20 个服务时这是灾难。

5.2.2 Sleuth 的贡献与谢幕

Spring Cloud Sleuth 早期做了两件最重要的事:

  1. 自动生成 TraceId/SpanId 并注入到日志 MDC
  2. 通过 HTTP Header 跨服务传播X-B3-TraceIdX-B3-SpanId

经典日志格式:

复制代码
2024-10-20 10:00:01.123 INFO [order-service, abc123, def456, true] 创建订单成功
                                  └─服务名   └─TraceId └─SpanId └─是否上报

⚠️ Spring Boot 3.x 中 Sleuth 被 Micrometer Tracing 取代,API 发生重大变化。


5.3 怎么做 --- Micrometer Tracing + Zipkin 完整集成

5.3.1 小 Demo:先暴露痛点

在 Provider 中故意加延时模拟慢查询:

java 复制代码
@GetMapping(value = "/pay/get/{id}")
public ResultData<Pay> getById(@PathVariable("id") Integer id) {
    // 模拟慢查询:故意 sleep 62 秒
    try { TimeUnit.SECONDS.sleep(62); } catch (Exception e) { e.printStackTrace(); }
    return ResultData.success(payService.getById(id));
}

Consumer 调用后:不知道 Provider 内部耗时多少,日志里只有一个总耗时

5.3.2 6 个核心依赖详解

序号 依赖 GAV 作用
1 micrometer-tracing-bom io.micrometer BOM 版本管理,统一版本
2 micrometer-tracing io.micrometer 核心 API,创建 Trace/Span
3 micrometer-tracing-bridge-brave io.micrometer 将 Micrometer API 桥接到 Brave(Zipkin 的 Java 实现)
4 micrometer-observation io.micrometer Observation API,统一 metrics/tracing/logging
5 feign-micrometer io.github.openfeign 让 Feign 客户端自动生成 Span
6 zipkin-reporter-brave io.zipkin.reporter2 将 Span 数据异步发送到 Zipkin Server
xml 复制代码
<!-- 父 POM 中统一管理版本 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-tracing-bom</artifactId>
            <version>1.2.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

5.3.3 Provider 端配置

yaml 复制代码
# 注意:Spring Boot 3.x 中配置前缀改变了!
management:
  zipkin:
    tracing:
      endpoint: http://localhost:9411/api/v2/spans  # Zipkin Server 地址
  tracing:
    sampling:
      probability: 1.0  # 采样率:开发=1.0(全部),生产=0.1(10%)

5.3.4 Consumer 端无需额外配置

Feign 自动传播 TraceId:feign-micrometer 会在每次 Feign 请求的 Header 中自动注入 traceparent(W3C 标准格式)。

5.3.5 启动 Zipkin Server

bash 复制代码
# Docker 方式
docker run -d -p 9411:9411 openzipkin/zipkin

# 或下载 jar
curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

5.3.6 验证

访问 Consumer → Provider → 打开 http://localhost:9411 → 点击"Run Query":

复制代码
Trace: 5f7a3b2c1d4e...
  ├── cloud-consumer-order-openfeign:  5ms
  │    └── cloud-payment-service:    62s    ← 一眼定位!
  └── Total: 62s

5.4 深入原理

5.4.1 Trace 传播机制

复制代码
Consumer                          Provider
   │                                 │
   │  GET /feign/micrometer/1        │
   │  Header: traceparent:            │
   │    00-abc123-def456-01          │
   │ ──────────────────────────────→ │
   │                                 │ 提取 TraceId=abc123
   │                                 │ 创建新 Span,parentSpanId=def456
   │                                 │
   │  ← 200 OK                       │
   │                                 │
   ├→ 上报 Span(consumer-side) → Zipkin
   └→ 上报 Span(provider-side) → Zipkin

W3C Trace Context 标准 Header

复制代码
traceparent: 00-{trace-id}-{parent-span-id}-{trace-flags}
              │  │          │              └─ 01=采样
              │  │          └─ 父 Span ID
              │  └─ 全局 Trace ID(32位hex)
              └─ 版本号(当前为 00)

5.4.2 采样策略

策略 配置 效果
Always 全部采样 probability: 1.0 开发环境、排查问题
Probability 按比例 probability: 0.1 生产环境,10% 采样
RateLimit 每秒N条 需自定义 Sampler 按秒限制总条数
Never 不采样 probability: 0 关闭追踪
java 复制代码
// 自定义采样器 Bean
@Bean
public SamplerFunction<HttpRequest> mySampler() {
    return request -> {
        // 健康检查接口不采样
        if (request.path().startsWith("/actuator")) return false;
        return true;
    };
}

5.5 对比分析

维度 Sleuth Micrometer Tracing
Spring Boot 版本 2.x 3.x
底层 API Brave/OpenTelemetry Observation API 统一抽象
配置前缀 spring.sleuth.* management.tracing.*
日志 MDC 自动注入 TraceId/SpanId 需手动配置 logging.pattern.level
Feign 集成 spring-cloud-sleuth feign-micrometer
未来方向 停止维护 Spring 主推

5.6 面试题

Q1:Sleuth 和 Micrometer Tracing 的核心区别?

  1. Sleuth 仅用于 Spring Boot 2.x,Micrometer Tracing 用于 3.x。
  2. Micrometer Tracing 使用 Observation API 统一了 metrics/tracing/logging 三个维度。
  3. 配置前缀从 spring.sleuth.* 变为 management.tracing.*
  4. Micrometer Tracing 是 Spring 官方的长远方向。

Q2:TraceId 是如何跨服务传播的?

:通过 HTTP Header 传播。Feign 自动在请求中添加 traceparent(W3C 标准)或 X-B3-TraceId 等 Header,下游服务从 Header 中提取 TraceId,创建子 Span。

Q3:高并发场景下如何平衡链路追踪的性能开销?

  1. 降低采样率 :生产环境设为 0.010.1(1%10%)
  2. 使用异步上报:Zipkin Reporter 默认异步,不阻塞业务线程
  3. 配置 Span 数量上限:单个 Trace 最多创建 N 个 Span
  4. 使用消息队列缓冲:Zipkin → Kafka → Zipkin Server

5.7 踩坑指南

现象 原因 解决
🔴 配置不生效 Zipkin 收不到数据 Spring Boot 3.x 配置前缀从 spring.zipkin 改为 management.zipkin 检查配置路径
🔴 Feign 不传播 TraceId Zipkin 中 Consumer 和 Provider 是两条独立的 Trace 缺少 feign-micrometer 依赖 必须引入 6 个依赖中的第 5 个
🔴 采样率 1.0 导致 OOM Zipkin 内存爆炸 生产环境全量采样产生海量 Span 生产设为 0.1
🔴 Zipkin 端口冲突 Zipkin 启动失败 9411 端口被占用 换端口或 kill 占用进程

5.8 章节总结

要点 说明
核心概念 Trace(全局链路)+ Span(每个节点)+ Propagation(跨服务传递)
Sleuth→Micrometer Spring Boot 3.x 中 Sleuth 被取代,API 和配置前缀都变了
6 个依赖 tracing + brave-bridge + observation + feign-micrometer + zipkin-reporter + tracing-bom
关键配置 management.zipkin.tracing.endpoint + management.tracing.sampling.probability
Feign 自动传播 feign-micrometer 自动在 Header 中注入 W3C 标准的 traceparent
采样率 开发 1.0,生产 0.01~0.1
相关推荐
PixelBai1 小时前
JSON差异比较高级用法技巧
java·服务器·json
晓杰在写后端1 小时前
从0到1实现Balatro游戏后端(7):Boss Blind与特殊规则实现
后端·游戏开发
iiiiyu1 小时前
IO流相关编程题
java·大数据·开发语言·数据结构·数据库·mysql
ANnianStriver1 小时前
PetLumina 06 — 图片上传全链路
java·ai·ai编程·文件上传·cos·腾讯云对象存储
这个DBA有点耶1 小时前
核心系统的高可用与容灾架构:从主从到两地三中心全面解析
java·开发语言·数据库·sql·mysql·架构·运维开发
AC赳赳老秦1 小时前
OpenClaw+AWS 深度应用:自动生成 CloudFormation 模板、批量管理 S3 存储桶
java·python·面试·职场和发展·php·deepseek·openclaw
用户298698530141 小时前
Java 处理 Word 文档:如何批量修改超链接地址与显示文本
java·后端
爱勇宝1 小时前
《置身钉内》之后:普通前端的出路在哪里?
前端·后端·程序员
asdfg12589631 小时前
BeanListHandler的通俗理解
java·数据库·oracle