<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Spring Cloud Sleuth on 小蜜蜂</title>
        <link>https://xumf.net/tags/spring-cloud-sleuth/</link>
        <description>Recent content in Spring Cloud Sleuth on 小蜜蜂</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 01 Aug 2024 13:54:50 +0800</lastBuildDate><atom:link href="https://xumf.net/tags/spring-cloud-sleuth/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Spring Cloud Sleuth</title>
            <link>https://xumf.net/blog/springcloudsleuth/</link>
            <pubDate>Thu, 01 Aug 2024 13:54:50 +0800</pubDate>
            <guid>https://xumf.net/blog/springcloudsleuth/</guid>
            <description>&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Spring Cloud Sleuth 已在 Spring Boot 3.x / Spring Cloud 2022.0.x 中被 &lt;strong&gt;Micrometer Tracing&lt;/strong&gt; 取代。新项目直接使用 Micrometer Tracing，旧项目建议迁移。本文基于 Sleuth 2.x 版本。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;分布式追踪核心概念&#34;&gt;分布式追踪核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;为什么需要链路追踪&#34;&gt;为什么需要链路追踪？&#xA;&lt;/h3&gt;&lt;p&gt;微服务架构中，一个请求可能需要经过多个服务。当请求变慢或报错时，没有链路追踪很难定位问题出在哪个服务、哪个环节。链路追踪通过 Trace ID 将一次请求跨服务的调用串联起来。&lt;/p&gt;&#xA;&lt;h3 id=&#34;核心术语&#34;&gt;核心术语&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Trace&lt;/strong&gt;：一次完整的请求链路，用唯一的 Trace ID 标识&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Span&lt;/strong&gt;：一个工作单元（如一次 RPC 调用、一次数据库查询），包含开始和结束时间&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Annotation&lt;/strong&gt;：关键事件标记，记录请求在不同阶段的时间戳&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Trace (traceId=abc)&#xA;├── Span 1 (id=1, parentId=null) —— 入口服务&#xA;│   ├── cs (Client Sent): 时间戳 T1&#xA;│   ├── sr (Server Received): 时间戳 T2 —— 下游服务收到&#xA;│   ├── ss (Server Sent): 时间戳 T3 —— 下游服务返回&#xA;│   └── cr (Client Received): 时间戳 T4&#xA;└── Span 2 (id=2, parentId=1) —— 下游服务调数据库&#xA;    ├── cs: 时间戳 T5&#xA;    └── cr: 时间戳 T6&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;通过这 4 个时间点可以计算出：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;网络延迟&lt;/strong&gt;：sr - cs（请求发送耗时）+ cr - ss（响应传输耗时）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务处理时间&lt;/strong&gt;：ss - sr（下游服务实际处理耗时）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;总耗时&lt;/strong&gt;：cr - cs&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;sleuth-核心功能&#34;&gt;Sleuth 核心功能&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;自动生成并传播 Trace ID 和 Span ID（通过 HTTP Header 或消息头）&lt;/li&gt;&#xA;&lt;li&gt;集成 Zipkin 等追踪后端&lt;/li&gt;&#xA;&lt;li&gt;支持多种通信协议（HTTP、消息队列、gRPC）&lt;/li&gt;&#xA;&lt;li&gt;日志自动关联——日志中自动添加 &lt;code&gt;[appname, traceId, spanId, exportable]&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;2024-08-01 10:00:00.123 [http-nio-8080-exec-1] [myapp, 2485ec27856c56f4, 2485ec27856c56f4, true] INFO  - 请求开始&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;通过这个格式，可以按 traceId 筛选出某个请求在所有服务中的完整日志。&lt;/p&gt;&#xA;&lt;h2 id=&#34;源码分析&#34;&gt;源码分析&#xA;&lt;/h2&gt;&lt;h3 id=&#34;tracer-接口&#34;&gt;Tracer 接口&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Tracer&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Span &lt;span style=&#34;color:#a6e22e&#34;&gt;nextSpan&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Span &lt;span style=&#34;color:#a6e22e&#34;&gt;nextSpan&lt;/span&gt;(Span parent);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Span &lt;span style=&#34;color:#a6e22e&#34;&gt;newTrace&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;continueSpan&lt;/span&gt;(Span span);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(Span span);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Span &lt;span style=&#34;color:#a6e22e&#34;&gt;currentSpan&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tracer 负责 Span 的创建和管理。&lt;code&gt;newTrace()&lt;/code&gt; 创建全新的 Trace（入口请求），&lt;code&gt;nextSpan()&lt;/code&gt; 基于当前 Trace 创建子 Span。&lt;/p&gt;&#xA;&lt;h3 id=&#34;tracecontext-传播&#34;&gt;TraceContext 传播&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Propagator&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;C&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt;(TraceContext context, C carrier, Setter&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;C&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; setter);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;C&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; Span.&lt;span style=&#34;color:#a6e22e&#34;&gt;Builder&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;extract&lt;/span&gt;(C carrier, Getter&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;C&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; getter);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;inject&lt;/code&gt; 将 TraceContext 写入 HTTP Header（如 &lt;code&gt;X-B3-TraceId&lt;/code&gt;），&lt;code&gt;extract&lt;/code&gt; 从请求头中提取并恢复上下文。这是跨服务传播的核心接口。&lt;/p&gt;&#xA;&lt;h3 id=&#34;自动配置&#34;&gt;自动配置&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Configuration&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@ConditionalOnProperty&lt;/span&gt;(value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;spring.sleuth.enabled&amp;#34;&lt;/span&gt;, matchIfMissing &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;TraceAutoConfiguration&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Tracer &lt;span style=&#34;color:#a6e22e&#34;&gt;tracer&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DefaultTracer();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CurrentTraceContext &lt;span style=&#34;color:#a6e22e&#34;&gt;currentTraceContext&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ThreadLocalCurrentTraceContext.&lt;span style=&#34;color:#a6e22e&#34;&gt;create&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;重要知识点&#34;&gt;重要知识点&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-sleuth-如何实现跨服务上下文传播&#34;&gt;1. Sleuth 如何实现跨服务上下文传播？&#xA;&lt;/h3&gt;&lt;p&gt;Sleuth 通过 Brave（Zipkin 的 Java 客户端库）实现上下文传播。HTTP 请求经过 RestTemplate / Feign / WebClient 时，Sleuth 自动注入以下 Header：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;X-B3-TraceId&lt;/code&gt;：全局唯一的 Trace ID&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-B3-SpanId&lt;/code&gt;：当前 Span ID&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-B3-ParentSpanId&lt;/code&gt;：父 Span ID&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-B3-Sampled&lt;/code&gt;：是否采样&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-B3-Flags&lt;/code&gt;：调试标记&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;下游服务收到请求后，从 Header 中提取 &lt;code&gt;X-B3-TraceId&lt;/code&gt;，创建子 Span 并将自己作为当前 Trace 的一部分。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-trace-和-span-的关系&#34;&gt;2. Trace 和 Span 的关系？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;一个 Trace 由多个 Span 组成，形成&lt;strong&gt;树状结构&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;根 Span（第一个 Span）没有 parentId&lt;/li&gt;&#xA;&lt;li&gt;子 Span 通过 parentId 引用父 Span&lt;/li&gt;&#xA;&lt;li&gt;所有 Span 共享同一个 traceId&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3-如何自定义-span&#34;&gt;3. 如何自定义 Span？&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Autowired&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Tracer tracer;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;customSpan&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Span span &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;nextSpan&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-operation&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; (Tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;SpanInScope&lt;/span&gt; ws &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;withSpanInScope&lt;/span&gt;(span)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 业务逻辑&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        span.&lt;span style=&#34;color:#a6e22e&#34;&gt;tag&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-key&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-value&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        span.&lt;span style=&#34;color:#a6e22e&#34;&gt;annotate&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-event&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        span.&lt;span style=&#34;color:#a6e22e&#34;&gt;finish&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：&lt;code&gt;start()&lt;/code&gt; 只调用一次，&lt;code&gt;finish()&lt;/code&gt; 会在 finally 中确保执行。使用 &lt;code&gt;withSpanInScope&lt;/code&gt; 将当前 Span 绑定到线程上下文。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-sleuth-与-zipkin-集成&#34;&gt;4. Sleuth 与 Zipkin 集成？&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spring&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;zipkin&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;base-url&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://localhost:9411&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;sender&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;type: web     # 发送方式&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;web/kafka/rabbitmq&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;sleuth&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;sampler&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;probability: 1.0  # 采样率&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;~1，生产环境建议 0.1 以下&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;采样率说明：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;1.0&lt;/code&gt;：100% 采样，开发和调试时使用&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;0.1&lt;/code&gt;：10% 采样，生产环境常用——追踪数据量大时存储和网络压力不可忽视&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;0.01&lt;/code&gt;：1% 采样，高流量系统的保守选择&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;5-sleuth-对各种通信方式的支持&#34;&gt;5. Sleuth 对各种通信方式的支持？&#xA;&lt;/h3&gt;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;通信方式&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;支持情况&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;说明&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;RestTemplate&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;自动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通过 ClientHttpRequestInterceptor&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Feign&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;自动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通过 Feign 的 RequestInterceptor&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;WebClient&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;自动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通过 ExchangeFilterFunction&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;RabbitMQ&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;自动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通过消息头传播&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Kafka&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;自动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通过消息头传播&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;gRPC&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;依赖扩展&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;需额外配置&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;线程池&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;需要手动&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;使用 &lt;code&gt;Tracer.withSpanInScope&lt;/code&gt; 或 &lt;code&gt;LazyTraceExecutor&lt;/code&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;6-sleuth-的性能影响&#34;&gt;6. Sleuth 的性能影响？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Sleuth 本身非常轻量，主要开销在：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Trace ID 的生成和传播（极低）&lt;/li&gt;&#xA;&lt;li&gt;数据发送到 Zipkin（异步，不阻塞请求线程）&lt;/li&gt;&#xA;&lt;li&gt;采样率高时，Zipkin 存储可能成为瓶颈&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;生产环境建议：&lt;code&gt;probability: 0.01~0.1&lt;/code&gt; + 使用 Kafka 作为 Reporter（避免 HTTP 发送阻塞）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;7-sleuth-如何支持异步操作&#34;&gt;7. Sleuth 如何支持异步操作？&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 方法一：手动绑定上下文&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mono.&lt;span style=&#34;color:#a6e22e&#34;&gt;just&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;doOnNext&lt;/span&gt;(value &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Span span &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;nextSpan&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;async-operation&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; (Tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;SpanInScope&lt;/span&gt; ws &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tracer.&lt;span style=&#34;color:#a6e22e&#34;&gt;withSpanInScope&lt;/span&gt;(span)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 异步逻辑&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#66d9ef&#34;&gt;finally&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            span.&lt;span style=&#34;color:#a6e22e&#34;&gt;finish&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 方法二：使用 Sleuth 提供的 LazyTraceExecutor&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;asyncExecutor&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; LazyTraceExecutor(tracer, Executors.&lt;span style=&#34;color:#a6e22e&#34;&gt;newFixedThreadPool&lt;/span&gt;(10));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;排查思路&#34;&gt;排查思路&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Trace ID 未在日志中出现&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;确认 &lt;code&gt;spring.sleuth.enabled&lt;/code&gt; 未被设置为 false&lt;/li&gt;&#xA;&lt;li&gt;确认日志格式正确（Sleuth 通过 &lt;code&gt;MDC&lt;/code&gt; 注入 traceId）&lt;/li&gt;&#xA;&lt;li&gt;检查是否使用了自定义 RestTemplate 或 Feign，可能覆盖了默认拦截器&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;调用链不完整&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;确认所有参与链路的服务都配置了 Sleuth&lt;/li&gt;&#xA;&lt;li&gt;确认服务间的调用方式（HTTP/消息队列）被 Sleuth 支持&lt;/li&gt;&#xA;&lt;li&gt;检查异步操作中是否丢失了上下文——使用 &lt;code&gt;Tracer.withSpanInScope&lt;/code&gt; 或 &lt;code&gt;LazyTraceExecutor&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Zipkin 看不到数据&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;spring.zipkin.base-url&lt;/code&gt; 是否正确&lt;/li&gt;&#xA;&lt;li&gt;检查网络连通性（从应用程序到 Zipkin Server）&lt;/li&gt;&#xA;&lt;li&gt;检查采样率设置：&lt;code&gt;probability: 0&lt;/code&gt; 会导致不发送任何数据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;迁移到 Micrometer Tracing 的注意点&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;配置从 &lt;code&gt;spring.sleuth.*&lt;/code&gt; 变为 &lt;code&gt;management.tracing.*&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Trace ID 格式从 64-bit（Sleuth 默认）变为 128-bit（Micrometer 默认）&lt;/li&gt;&#xA;&lt;li&gt;依赖从 &lt;code&gt;spring-cloud-starter-sleuth&lt;/code&gt; 变为 &lt;code&gt;io.micrometer:micrometer-tracing-bridge-brave&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item></channel>
</rss>
