← 返回题目列表

微服务分布式链路追踪的原理是什么?Spring Cloud Sleuth 现在还能用吗?

高频 中等 第 4 / 24 题 更新于 2026/07/26
分布式追踪Micrometer TracingTraceIdSleuth

简化版

分布式追踪用 Trace 表示一次跨服务调用链,用 Span 表示其中一个操作,并通过 HTTP 或消息头传播 Trace Context,使各服务生成的 Span 能关联起来。Spring Boot 3 时代 Sleuth 的能力已迁入 Micrometer Tracing,Sleuth 不支持 Spring Boot 3,新项目应使用 Micrometer Observation/Tracing 及对应导出器。

详细版

入口收到请求时创建或继续 Trace,当前服务创建 Span,调用下游前注入 traceId、spanId 和采样标记,下游提取上下文后创建子 Span。完成后的数据按采样策略导出到 Zipkin、OTLP 兼容后端等系统,日志可通过 MDC 关联 traceId。

链路传播依赖受支持客户端和线程上下文。手动创建线程、未被观测的 HTTP 客户端或消息消费者可能丢失上下文;响应式代码还依赖 Reactor Context,不能只用 ThreadLocal 思路处理。

完整版教学

一、Trace 与 Span

Trace: 用户下单
  Span: Gateway 接收请求
    Span: OrderService 创建订单
      Span: InventoryService 扣库存
      Span: PaymentService 发起支付

同一 Trace 共享 traceId,每个 Span 有自己的 spanId 和父子关系,并记录开始时间、耗时、状态、事件与有限属性。它能展示延迟花在哪一跳,但不能自动解释业务为什么错误。

概念粒度典型字段作用
Trace一次完整请求链traceId把跨服务调用串起来
Span一次操作或一次远程调用spanId、parentId、耗时定位每一跳耗时和状态
Context当前追踪上下文traceId、spanId、sampled在线程、HTTP、消息之间传播
Baggage随链路传播的少量业务上下文tenant、region给下游读取,但要严格控制

记忆钩子:Trace 是整条线,Span 是线上每一段,Context 是把线从一个进程接到下一个进程的接头。

二、上下文如何跨进程

调用方把追踪上下文注入请求头或消息元数据,下游提取后继续链路。常见传播格式包括 W3C Trace Context 和 B3,所有服务必须配置兼容格式;格式不一致会产生断裂的新 Trace。

网关、Feign、RestClient、WebClient 和消息组件在相应观测集成存在时可自动传播。自定义客户端要使用 Tracing API 或已观测的构建器,不能手工拼一个 traceId 就认为完成了追踪。

三、Observation、Tracing 与 Metrics

Micrometer Observation 描述一次可观测操作,Handler 可据此产生指标或追踪数据。Tracing Bridge 再对接 Brave、OpenTelemetry 等 tracer 实现,导出器负责把数据发送到后端。

抽象层、实现层和后端要分开:Micrometer Tracing 不等于某个具体追踪存储,使用 OTLP 也不代表必须绑定某一家平台。

四、采样为什么必要

全量追踪在高流量系统会产生大量 CPU、网络和存储开销,因此通常只采样部分 Trace。未采样请求仍可能传播基本上下文,但不会生成完整可导出数据,排查时不能把“后端搜不到”直接等同于请求没发生。

采样率应结合错误率、流量和成本设置。需要保留所有错误链路时,还要看所用 tracer 与后端是否支持尾部采样等能力,不能只依赖入口随机采样。

QPS = 10000
每条 Trace 平均 8 个 Span
全量:10000 × 8 = 80000 Span/s
采样 1%:约 800 Span/s

这个数字说明为什么高流量系统很少无脑全量追踪。采样降低成本,但也会让低频问题更难复现;所以常见策略是普通请求低采样,错误、慢请求或重点租户提高保留比例。

五、标签与 Baggage 风险

Span tag 用于检索和分析,但订单号、用户 ID 等高基数值会增加后端索引成本。密码、Token 和完整请求体不应写入 Span 或 Baggage。

Baggage 会随调用传播,字段越多,请求头和消息体积越大。只有下游确实需要的少量上下文才适合传播,业务数据应通过正式接口参数传递。

六、异步与日志关联

线程池切换会破坏单纯 ThreadLocal 上下文,必须使用框架提供的上下文传播支持。Reactor 可能在同一线程交错处理多个请求,更不能把追踪状态永久放在线程变量中。

日志中的 traceId 方便从错误日志跳到调用链,但日志、指标和追踪各有职责:指标发现异常趋势,追踪定位跨服务耗时,日志提供具体事件,三者应互相链接而不是互相替代。

面试里可以按排障顺序表达:

  • 先看指标判断是不是整体变慢或错误率升高;
  • 再用 traceId 找到具体 Trace,定位是哪一跳耗时异常;
  • 最后回到日志查看该 Span 附近的业务事件和异常堆栈。

这样回答能说明链路追踪不是孤立工具,而是可观测性三件套中的一环。

七、常见误区与追问

  • 误区:有 traceId 就等于完整链路追踪。 只有上下游都正确传播 Context 并创建 Span,才能还原父子关系和耗时。
  • 误区:Sleuth 在 Spring Boot 3 新项目里仍是默认方案。 Sleuth 属于 Boot 2 时代,新项目应使用 Micrometer Observation/Tracing。
  • 追问:W3C Trace Context 和 B3 为什么要统一? 传播格式不一致会导致上下游无法识别同一上下文,链路被切成多个 Trace。
  • 追问:为什么不能把用户 ID 随便放进 tag? 高基数字段会显著增加后端索引和存储成本,敏感字段还会带来合规风险。
  • 误区:追踪可以替代日志和指标。 指标看趋势,追踪看跨服务路径,日志看具体事件,三者互补。
  • 追问:异步线程为什么容易丢 Trace? ThreadLocal 不会自动跨线程传播,线程池和 Reactor 需要框架提供的上下文传播机制。

八、加强记忆

Trace 串整条链,Span 记一次操作,上下文靠标准请求头或消息元数据跨进程传播。Boot 3 使用 Micrometer Observation/Tracing,Sleuth 属于 Boot 2 时代;采样、异步上下文、高基数标签和敏感 Baggage 是落地时的关键边界。