<?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 on 小蜜蜂</title>
        <link>https://xumf.net/tags/spring-cloud/</link>
        <description>Recent content in Spring Cloud on 小蜜蜂</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Wed, 07 May 2025 23:04:30 +0800</lastBuildDate><atom:link href="https://xumf.net/tags/spring-cloud/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Zuul</title>
            <link>https://xumf.net/blog/zuul/</link>
            <pubDate>Wed, 07 May 2025 23:04:30 +0800</pubDate>
            <guid>https://xumf.net/blog/zuul/</guid>
            <description>&lt;h2 id=&#34;zuul-的核心概念&#34;&gt;Zuul 的核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1zuul-是什么&#34;&gt;（1）Zuul 是什么？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Zuul 是 Netflix 开源的 API 网关，用于微服务架构中的路由、过滤和负载均衡&lt;/li&gt;&#xA;&lt;li&gt;主要功能：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;路由：将客户端请求转发到后端服务&lt;/li&gt;&#xA;&lt;li&gt;过滤：在请求和响应的生命周期中执行自定义逻辑&lt;/li&gt;&#xA;&lt;li&gt;负载均衡：与 Ribbon 集成，实现客户端负载均衡&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2zuul-的工作流程&#34;&gt;（2）Zuul 的工作流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;路由：根据配置请求转发到对应的微服务&lt;/li&gt;&#xA;&lt;li&gt;过滤：在请求到达目标服务之前或之后执行过滤逻辑&lt;/li&gt;&#xA;&lt;li&gt;负载均衡：通过 Ribbon 集成，实现客户端负载均衡&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;zuul-的配置&#34;&gt;Zuul 的配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1依赖配置&#34;&gt;（1）依赖配置&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;在 pom.xml 添加 Zuul 依赖：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dependency&amp;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:#f92672&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.cloud&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/groupId&amp;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:#f92672&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-starter-netflix-zuul&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/artifactId&amp;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:#f92672&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2启用-zuul&#34;&gt;（2）启用 Zuul&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;在启动类中添加 &lt;strong&gt;@EnableZuulProxy&lt;/strong&gt; 注解：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;@SpringBootApplication&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;@EnableZuulProxy&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;ZuulApplication&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;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SpringAppliction.&lt;span style=&#34;color:#a6e22e&#34;&gt;run&lt;/span&gt;(ZuulApplication.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;, args);&#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;h3 id=&#34;3路由配置&#34;&gt;（3）路由配置&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;在 application.yml 中配置路由规则：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;zuul:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    routes:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        user&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;service: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt; 路径名称&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;user&lt;span style=&#34;color:#f92672&#34;&gt;/**&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt; 路径配置&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serviceId: user&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;service &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt; 目标服务名称&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        order&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;service:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            path: &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;order&lt;span style=&#34;color:#f92672&#34;&gt;/**&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            serviceId: order&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;解释：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;user-service 和 order-service 是路由的名称，可以自定义&lt;/li&gt;&#xA;&lt;li&gt;path 是匹配的 URL 路径&lt;/li&gt;&#xA;&lt;li&gt;serviceId 是 Eureka 中注册的服务名称&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;自定义路由&#xA;&lt;ul&gt;&#xA;&lt;li&gt;如果不想使用服务名称作为路由前缀，可以自定义路由：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;zuul&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;routes&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;custom-user-service&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:#f92672&#34;&gt;path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/user/**&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:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://localhost:8081&lt;/span&gt; &lt;span style=&#34;color:#75715e&#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集成-ribbon&#34;&gt;（1）集成 Ribbon&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Zuul 默认集成了 Ribbon，可以通过服务名称实现负载均衡&lt;/li&gt;&#xA;&lt;li&gt;在 &lt;strong&gt;application.yml&lt;/strong&gt; 中配置 Ribbon：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;zuul&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;routes&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;custom-user-service&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;path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/user/**&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;serviceId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;custom-user-service&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:#f92672&#34;&gt;custom-user-service&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;ribbon&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;listOfServers&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://localhost:8081,http://localhost:8082&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:#f92672&#34;&gt;NFLoadBalancerRuleClassName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;com.netflix.loadbalancer.RandomRule&lt;/span&gt; &lt;span style=&#34;color:#75715e&#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;实例完整的-zuul-配置&#34;&gt;实例：完整的 Zuul 配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1applicationyml&#34;&gt;（1）application.yml&#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;user-service&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;ribbon&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;listOfServers&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://localhost:8081,http://localhost:8082&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;# 目标服务实例列表&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2启动类&#34;&gt;（2）启动类&#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;@SpringBootApplication&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;@EnableZuulProxy&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;ZuulApplication&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;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SpringAppliction.&lt;span style=&#34;color:#a6e22e&#34;&gt;run&lt;/span&gt;(ZuulApplication.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;, args);&#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;zuul-与-spring-cloud-gateway对比&#34;&gt;Zuul 与 Spring Cloud Gateway对比&#xA;&lt;/h2&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;Spring Cloud Gateway&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Spring Cloud Zuul 1.x&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;架构模型&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;异步非阻塞 (基于 WebFlux 和 Reactor)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;同步阻塞 (基于 Servlet)&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;/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;/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;较低 (基于 Netty)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;较高 (基于 Servlet 容器)&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;/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;集成 Spring Cloud LoadBalancer&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;使用 Ribbon&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;/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;使用 Netty 连接池&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;原生支持 HTTP/2&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;主要支持 HTTP/1.1&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;/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;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;</description>
        </item><item>
            <title>Zipkin</title>
            <link>https://xumf.net/blog/zipkin/</link>
            <pubDate>Mon, 03 Mar 2025 22:19:24 +0800</pubDate>
            <guid>https://xumf.net/blog/zipkin/</guid>
            <description>&lt;p&gt;Zipkin 是 Twitter 开源的分布式链路追踪系统，用于收集和查看微服务架构中的请求链路数据。它与 Spring Cloud Sleuth（或 Micrometer Tracing）配合使用——Sleuth 负责生成和传播 Trace 数据，Zipkin 负责存储和展示。&lt;/p&gt;&#xA;&lt;h2 id=&#34;架构组成&#34;&gt;架构组成&#xA;&lt;/h2&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-plain&#34; data-lang=&#34;plain&#34;&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;| Collector | &amp;lt;-- | Reporter | &amp;lt;-- | Instrument|&#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;      v                  v&#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;| Storage   |     | UI        |&#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;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Instrument&lt;/strong&gt;：应用中嵌入的追踪客户端（Brave / Sleuth），生成 Span 数据&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Reporter&lt;/strong&gt;：将 Span 数据异步发送到 Zipkin Server。支持 HTTP、Kafka、RabbitMQ&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Collector&lt;/strong&gt;：接收、验证、存储 Span 数据&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Storage&lt;/strong&gt;：持久化存储（内存/MySQL/ElasticSearch/Cassandra）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;UI&lt;/strong&gt;：Web 界面查询和可视化链路&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;数据模型&#34;&gt;数据模型&#xA;&lt;/h2&gt;&lt;h3 id=&#34;span-数据结构&#34;&gt;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:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Span&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; Serializable {&#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;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Builder&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; String traceId;       &lt;span style=&#34;color:#75715e&#34;&gt;// 全局唯一链路 ID&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; String parentId;      &lt;span style=&#34;color:#75715e&#34;&gt;// 父 Span ID（根 Span 为 null）&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; String id;            &lt;span style=&#34;color:#75715e&#34;&gt;// 当前 Span ID&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; String name;          &lt;span style=&#34;color:#75715e&#34;&gt;// Span 名称（如 &amp;#34;get /user/{id}&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;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;long&lt;/span&gt; timestamp;       &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;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;long&lt;/span&gt; duration;        &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;private&lt;/span&gt; List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Annotation&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; annotations;  &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;private&lt;/span&gt; Map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; tags;       &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;private&lt;/span&gt; Boolean shared;       &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;    }&#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;h3 id=&#34;关键-annotation&#34;&gt;关键 Annotation&#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;cs (Client Sent)&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;cr (Client Received)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;客户端收到响应&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;计算总耗时 = cr - cs&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;sr (Server Received)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;服务端收到请求&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;计算网络延迟 = sr - cs&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;ss (Server Sent)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;服务端发送响应&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;计算服务处理时间 = ss - sr&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;error&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;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;数据流&#34;&gt;数据流&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. 应用通过 Reporter 发送 Span 数据&#xA;2. Collector 接收并校验数据完整性&#xA;3. 数据存储到 Storage（可选择 ES/Cassandra/MySQL）&#xA;4. UI 从 Storage 查询并展示&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;reporter-发送方式对比&#34;&gt;Reporter 发送方式对比&#xA;&lt;/h2&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;&#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;HTTP（Web）&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;&#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;需要维护 Kafka 集群&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;RabbitMQ&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;类似 Kafka，与 Spring 生态更适配&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;需要维护 RabbitMQ&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;已有 RabbitMQ 的基础设施&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;Scribe&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;&#x9;&#x9;&lt;td&gt;历史遗留系统&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;使用 Kafka 推荐配置：&lt;/p&gt;&#xA;&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;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&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kafka&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;kafka&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;bootstrap-servers&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;localhost:9092&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Kafka 的优势：即使 Zipkin Server 短暂不可用，数据也不会丢失（Kafka 持久化缓冲）。&lt;/p&gt;&#xA;&lt;h2 id=&#34;存储后端选择&#34;&gt;存储后端选择&#xA;&lt;/h2&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;&#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;内存&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;&#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;MySQL&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;&#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;ElasticSearch&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;&#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;Cassandra&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;&#x9;&#x9;&lt;td&gt;超大规模集群&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;生产环境选择建议：&lt;strong&gt;ElasticSearch&lt;/strong&gt; 是最常用的选择，兼顾查询灵活性和写入性能。&lt;/p&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;全量采样（&lt;code&gt;probability: 1.0&lt;/code&gt;）在高并发下会产生大量数据——1000 QPS 的服务每天产生近亿条 Span。采样是必须的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;采样方式&#34;&gt;采样方式&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;固定比率采样&lt;/strong&gt;：默认，按百分比采样&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&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;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&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.01&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 采样 1%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;限速采样&lt;/strong&gt;：保证每秒最多采样条数&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&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;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;rate&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 每秒最多采样 10 条&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;自定义采样规则&lt;/strong&gt;：对某些路径全量采样（如支付、订单相关接口），其他路径降低采样率。需实现 &lt;code&gt;Sampler&lt;/code&gt; 接口。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;集成示例&#34;&gt;集成示例&#xA;&lt;/h2&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://zipkin-server: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&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;web&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;enabled&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:#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&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 启动 Zipkin Server（Docker）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -d -p 9411:9411 openzipkin/zipkin:latest&#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;Zipkin UI 看不到数据&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查应用能否访问 Zipkin Server：telnet zipkin-server 9411&lt;/li&gt;&#xA;&lt;li&gt;检查采样率是否为 0&lt;/li&gt;&#xA;&lt;li&gt;检查应用日志中是否出现 &lt;code&gt;ZipkinReporter&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;链路不完整&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;确认所有参与链路的服务都配置了 Zipkin&lt;/li&gt;&#xA;&lt;li&gt;检查异步调用是否丢失 TraceContext——异步线程池中需要手动传播上下文&lt;/li&gt;&#xA;&lt;li&gt;确认 Http Header 未被自定义过滤器清除（&lt;code&gt;X-B3-TraceId&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;ES：设置 ILM（Index Lifecycle Management）自动删除过期索引&lt;/li&gt;&#xA;&lt;li&gt;Cassandra：配置 TTL（Time To Live）&lt;/li&gt;&#xA;&lt;li&gt;MySQL：定期清理，或设置较短的数据保留期&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;Zipkin Collector 成为瓶颈：增加 Collector 实例数&lt;/li&gt;&#xA;&lt;li&gt;ES 写入过慢：降低采样率，或使用 Kafka 缓冲&lt;/li&gt;&#xA;&lt;li&gt;使用 &lt;code&gt;sender.type: kafka&lt;/code&gt; 将数据发送链路上的压力从应用线程转移到 Kafka&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;高可用部署&#34;&gt;高可用部署&#xA;&lt;/h2&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;多个 Zipkin Server 实例&#xA;    ↑  (Nginx 负载均衡)&#xA;Kafka 集群（缓冲区）&#xA;    ↑&#xA;应用实例（Reporter 写入 Kafka）&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;部署多个 Collector 实例，使用 Nginx/ALB 负载均衡&lt;/li&gt;&#xA;&lt;li&gt;使用 Kafka 作为 Reporter 和 Collector 之间的缓冲层&lt;/li&gt;&#xA;&lt;li&gt;存储后端 ES 集群健康状态决定数据可靠性——使用 3 节点 + 副本策略&lt;/li&gt;&#xA;&lt;li&gt;ES 使用 ILM 按天生成索引，设置保留天数自动清理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
        </item><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><item>
            <title>Spring Cloud Gateway</title>
            <link>https://xumf.net/blog/springcloudgateway/</link>
            <pubDate>Thu, 18 Jul 2024 23:13:45 +0800</pubDate>
            <guid>https://xumf.net/blog/springcloudgateway/</guid>
            <description>&lt;h2 id=&#34;spring-cloud-gateway-核心原理&#34;&gt;Spring Cloud Gateway 核心原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-为什么选择-gateway-而非-zuul&#34;&gt;1. 为什么选择 Gateway 而非 Zuul？&#xA;&lt;/h3&gt;&lt;p&gt;Spring Cloud Gateway 基于 &lt;strong&gt;Spring WebFlux&lt;/strong&gt; 和 &lt;strong&gt;Project Reactor&lt;/strong&gt;，采用反应式编程模型（非阻塞 I/O）。与 Zuul 1.x（基于 Servlet API，同步阻塞）相比：&lt;/p&gt;&#xA;&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;Gateway&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Zuul 1.x&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Zuul 2.x&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;底层模型&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Netty + WebFlux&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Tomcat + Servlet&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Netty&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;I/O 模型&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;&#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;/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;/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;较高（需了解 Reactor）&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;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Gateway 的异步模型意味着：一个请求从进入到返回不占用独立线程，处理过程中线程可以服务其他请求，因此在高并发场景下线程资源占用远少于 Zuul 1.x。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-架构组成&#34;&gt;2. 架构组成&#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-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Client -&amp;gt; Gateway -&amp;gt; Route Predicate -&amp;gt; Gateway Filter -&amp;gt; Target Service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3-核心概念&#34;&gt;3. 核心概念&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Route&lt;/strong&gt;：路由，包含目标 URI、Predicate 集合和 Filter 集合&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Predicate&lt;/strong&gt;：断言，用于匹配 HTTP 请求（满足条件才走该路由）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Filter&lt;/strong&gt;：过滤器，用于修改请求和响应（分为 GatewayFilter 和 GlobalFilter）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4-工作流程&#34;&gt;4. 工作流程&#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-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1. 客户端发起请求&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2. Gateway Handler Mapping 查找匹配的路由（遍历所有 Route 的 Predicate 集合）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3. 执行 Gateway Filter 链（pre filters）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4. 代理请求到目标服务&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;5. 执行 Gateway Filter 链（post filters）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;6. 返回响应给客户端&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;5-关键组件&#34;&gt;5. 关键组件&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;RouteLocator&lt;/strong&gt;：路由定位器，定义路由规则&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;GatewayFilter&lt;/strong&gt;：网关过滤器（按路由配置）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;GlobalFilter&lt;/strong&gt;：全局过滤器（所有路由生效）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;RoutePredicateHandlerMapping&lt;/strong&gt;：路由断言处理器映射&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;WebHandler&lt;/strong&gt;：Web 请求处理器（底层由 WebFlux 的 DispatcherHandler 执行）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;重要知识点&#34;&gt;重要知识点&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-gateway-和-zuul-的区别&#34;&gt;1. Gateway 和 Zuul 的区别？&#xA;&lt;/h3&gt;&lt;p&gt;见上方对比表。核心差异在于&lt;strong&gt;线程模型&lt;/strong&gt;：Gateway 用少量线程处理大量请求（事件驱动），Zuul 1.x 每个请求对应一个线程（同步阻塞）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-gateway-的核心组件&#34;&gt;2. Gateway 的核心组件？&#xA;&lt;/h3&gt;&lt;p&gt;Route、Predicate、Filter（GatewayFilter + GlobalFilter）、RouteLocator、GatewayFilterFactory&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-如何自定义过滤器&#34;&gt;3. 如何自定义过滤器？&#xA;&lt;/h3&gt;&lt;p&gt;自定义 GatewayFilter 实现 GatewayFilter + Ordered 接口：&lt;/p&gt;&#xA;&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;@Component&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;CustomFilter&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; GatewayFilter, Ordered {&#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;@Override&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; Mono&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Void&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;filter&lt;/span&gt;(ServerWebExchange exchange, GatewayFilterChain chain) {&#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;        String requestPath &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; exchange.&lt;span style=&#34;color:#a6e22e&#34;&gt;getRequest&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;getURI&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;getPath&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        exchange.&lt;span style=&#34;color:#a6e22e&#34;&gt;getAttributes&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;startTime&amp;#34;&lt;/span&gt;, System.&lt;span style=&#34;color:#a6e22e&#34;&gt;currentTimeMillis&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:#66d9ef&#34;&gt;return&lt;/span&gt; chain.&lt;span style=&#34;color:#a6e22e&#34;&gt;filter&lt;/span&gt;(exchange).&lt;span style=&#34;color:#a6e22e&#34;&gt;then&lt;/span&gt;(Mono.&lt;span style=&#34;color:#a6e22e&#34;&gt;fromRunnable&lt;/span&gt;(() &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;            &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;            Long startTime &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; exchange.&lt;span style=&#34;color:#a6e22e&#34;&gt;getAttribute&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;startTime&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;if&lt;/span&gt; (startTime &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&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;long&lt;/span&gt; cost &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; System.&lt;span style=&#34;color:#a6e22e&#34;&gt;currentTimeMillis&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; startTime;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                log.&lt;span style=&#34;color:#a6e22e&#34;&gt;info&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{} 耗时 {}ms&amp;#34;&lt;/span&gt;, requestPath, cost);&#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;&#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;@Override&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;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getOrder&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:#f92672&#34;&gt;-&lt;/span&gt;1; &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;    }&#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;注册方式：在 Route 定义中通过 &lt;code&gt;.filters(f -&amp;gt; f.filter(new CustomFilter()))&lt;/code&gt; 注入。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-gateway-如何实现负载均衡&#34;&gt;4. Gateway 如何实现负载均衡？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;集成 Spring Cloud LoadBalancer&lt;/li&gt;&#xA;&lt;li&gt;使用 &lt;strong&gt;lb://service-id&lt;/strong&gt; 格式的 URI（例如 &lt;code&gt;lb://user-service&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;Gateway 自动从注册中心（Nacos / Eureka）获取服务实例列表&lt;/li&gt;&#xA;&lt;li&gt;默认负载均衡算法为轮询（支持自定义 ReactiveLoadBalancer）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;5-如何实现限流&#34;&gt;5. 如何实现限流？&#xA;&lt;/h3&gt;&lt;p&gt;使用 RequestRateLimiter GatewayFilter，基于令牌桶算法：&lt;/p&gt;&#xA;&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;cloud&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;gateway&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;routes&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;id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;limit_route&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;uri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://example.org&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;filters&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;RequestRateLimiter&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;args&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;redis-rate-limiter.replenishRate&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10&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:#f92672&#34;&gt;redis-rate-limiter.burstCapacity&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;# 令牌桶容量&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：GateWay 的限流需要集成 Redis（基于 Redis 的 lua 脚本实现令牌桶），因此必须引入 &lt;code&gt;spring-boot-starter-data-redis-reactive&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h3 id=&#34;6-gateway-如何实现熔断&#34;&gt;6. Gateway 如何实现熔断？&#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;cloud&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;gateway&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;routes&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;id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;hystrix_route&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;uri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;lb://backing-service:8088&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;filters&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Hystrix&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;args&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;fallbackcmd&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;fallbackUri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;forward:/fallback&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：Hystrix 已进入维护状态，新项目推荐使用 &lt;strong&gt;Spring Cloud CircuitBreaker&lt;/strong&gt;（支持 Resilience4J）替代 Hystrix：&lt;/p&gt;&#xA;&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;filters&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CircuitBreaker&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;args&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;myCircuitBreaker&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;fallbackUri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;forward:/fallback&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;7-如何实现动态路由&#34;&gt;7. 如何实现动态路由？&#xA;&lt;/h3&gt;&lt;p&gt;实现 &lt;code&gt;RouteDefinitionRepository&lt;/code&gt; 接口，从数据库或配置中心加载路由：&lt;/p&gt;&#xA;&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;@Component&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;DynamicRouteService&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; ApplicationEventPublisherAware {&#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;@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; RouteDefinitionWriter routeDefinitionWriter;&#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;addRoute&lt;/span&gt;(RouteDefinition definition) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        routeDefinitionWriter.&lt;span style=&#34;color:#a6e22e&#34;&gt;save&lt;/span&gt;(Mono.&lt;span style=&#34;color:#a6e22e&#34;&gt;just&lt;/span&gt;(definition)).&lt;span style=&#34;color:#a6e22e&#34;&gt;subscribe&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        publisher.&lt;span style=&#34;color:#a6e22e&#34;&gt;publishEvent&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RefreshRoutesEvent(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&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;    }&#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;RefreshRoutesEvent&lt;/code&gt;，否则新路由不会生效。&lt;/p&gt;&#xA;&lt;h3 id=&#34;8-gateway-的安全机制&#34;&gt;8. Gateway 的安全机制？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;集成 Spring Security + OAuth2 / JWT&lt;/li&gt;&#xA;&lt;li&gt;支持 HTTPS&lt;/li&gt;&#xA;&lt;li&gt;支持 IP 白名单（通过自定义 GlobalFilter 实现）&lt;/li&gt;&#xA;&lt;li&gt;常见安全风险：Gateway 默认不校验重复路由、不限制请求体大小——生产环境需额外配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;9-gateway-的监控&#34;&gt;9. Gateway 的监控？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;集成 Actuator，&lt;code&gt;management.endpoints.web.exposure.include=gateway&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/actuator/gateway/routes&lt;/code&gt;：查看已加载的路由&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/actuator/gateway/globalfilters&lt;/code&gt;：查看已注册的全局过滤器&lt;/li&gt;&#xA;&lt;li&gt;结合 Micrometer + Prometheus + Grafana 采集请求延迟和错误率&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;10-gateway-如何处理跨域&#34;&gt;10. Gateway 如何处理跨域？&#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;cloud&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;gateway&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;globalcors&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;cors-configurations&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;#39;[/**]&amp;#39;&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;allowedOrigins&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*&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:#f92672&#34;&gt;allowedMethods&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:#ae81ff&#34;&gt;GET&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:#ae81ff&#34;&gt;POST&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:#ae81ff&#34;&gt;PUT&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:#ae81ff&#34;&gt;DELETE&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;allowedHeaders&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：Gateway 的位置特殊——跨域配置在网关层处理即可，后端服务无需重复配置 CORS。&lt;/p&gt;&#xA;&lt;h2 id=&#34;排查思路&#34;&gt;排查思路&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;路由不匹配&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 Predicate 顺序（多个 Predicate 为 AND 关系）&lt;/li&gt;&#xA;&lt;li&gt;查看日志：&lt;code&gt;RoutePredicateHandlerMapping&lt;/code&gt; 会打印 &amp;ldquo;Mapping found&amp;rdquo; 或 &amp;ldquo;No route found&amp;rdquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;转发失败&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;确认目标服务健康（直接访问目标服务接口验证）&lt;/li&gt;&#xA;&lt;li&gt;检查负载均衡 URI 格式是否以 lb:// 开头&lt;/li&gt;&#xA;&lt;li&gt;查看 Gateway 日志：&lt;code&gt;ReadTimeoutException&lt;/code&gt; 表示后端响应过慢&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;过滤器不生效&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;GlobalFilter 默认所有路由生效，GatewayFilter 须在路由配置中明确指定&lt;/li&gt;&#xA;&lt;li&gt;检查 Ordered 排序（低 order 值的过滤器先执行前置后执行后置）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;WebFlux 与旧版 Servlet 冲突&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;项目中不能同时存在 &lt;code&gt;spring-boot-starter-web&lt;/code&gt; 和 &lt;code&gt;spring-boot-starter-webflux&lt;/code&gt;，否则 Gateway 无法正常运行（Spring Boot 默认优先使用 Servlet 容器）。排查是否有其他模块引入了 web 依赖。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Spring Cloud Config</title>
            <link>https://xumf.net/blog/springcloudconfig/</link>
            <pubDate>Tue, 11 Jun 2024 15:40:53 +0800</pubDate>
            <guid>https://xumf.net/blog/springcloudconfig/</guid>
            <description>&lt;h2 id=&#34;核心概念&#34;&gt;核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1什么是-spring-cloud-config&#34;&gt;（1）什么是 Spring Cloud Config？&#xA;&lt;/h3&gt;&lt;p&gt;Spring Cloud Config 是分布式配置管理工具，用于集中管理微服务的配置文件。它解决的核心问题：微服务数量增加后，配置文件散落在各个服务中，修改一个配置需要逐个修改、重启。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2组成部分&#34;&gt;（2）组成部分&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Config Server&lt;/strong&gt;：配置中心服务器，从后端存储加载配置并通过 HTTP API 暴露&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Config Client&lt;/strong&gt;：配置客户端，启动时从 Config Server 拉取配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3核心特性&#34;&gt;（3）核心特性&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;集中化管理&lt;/strong&gt;：所有微服务配置统一存储在 Git/SVN/本地等后端&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;动态刷新&lt;/strong&gt;：通过 &lt;code&gt;/actuator/refresh&lt;/code&gt; 或 Spring Cloud Bus 实现不重启更新配置&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;多环境支持&lt;/strong&gt;：通过 &lt;code&gt;spring.profiles.active&lt;/code&gt; 加载对应环境的配置（如 &lt;code&gt;application-dev.yml&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;安全性&lt;/strong&gt;：支持配置内容的加密和解密（对称 AES 或非对称 RSA）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;版本控制&lt;/strong&gt;：Git 后端天然具备版本历史、回滚、分支管理能力&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;权限控制&lt;/strong&gt;：通过 Git 仓库权限 + Config Server 的 Spring Security 双重控制&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;高可用&lt;/strong&gt;：Config Server 可集群部署，通过注册中心实现负载均衡&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;工作原理&#34;&gt;工作原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;config-server-配置解析路径&#34;&gt;Config Server 配置解析路径&#xA;&lt;/h3&gt;&lt;p&gt;Config Server 根据客户端请求的 &lt;code&gt;{application}/{profile}/{label}&lt;/code&gt; 路径解析配置。例如客户端请求 &lt;code&gt;/my-app/dev/master&lt;/code&gt;，Config Server 会在 Git 仓库中查找：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;my-app-dev.yml&lt;/code&gt;（应用名+环境）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;my-app.yml&lt;/code&gt;（应用名级配置）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;application-dev.yml&lt;/code&gt;（全局环境配置）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;application.yml&lt;/code&gt;（全局默认配置）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;优先级：1 &amp;gt; 2 &amp;gt; 3 &amp;gt; 4（后面覆盖前面）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;bootstrap-上下文&#34;&gt;Bootstrap 上下文&#xA;&lt;/h3&gt;&lt;p&gt;Spring Cloud Config Client 使用 &lt;strong&gt;bootstrap context&lt;/strong&gt;（由 &lt;code&gt;bootstrap.yml&lt;/code&gt; 或 &lt;code&gt;bootstrap.properties&lt;/code&gt; 配置），它在主应用上下文创建之前启动，负责：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;从 Config Server 拉取配置&lt;/li&gt;&#xA;&lt;li&gt;将拉取的配置设置为 &lt;code&gt;Environment&lt;/code&gt; 属性源&lt;/li&gt;&#xA;&lt;li&gt;然后才创建主应用上下文&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这就是为什么 Config Server 地址必须在 &lt;code&gt;bootstrap.yml&lt;/code&gt; 而非 &lt;code&gt;application.yml&lt;/code&gt; 中配置——主上下文启动时必须已经有远程配置可用。&lt;/p&gt;&#xA;&lt;h3 id=&#34;配置加载顺序&#34;&gt;配置加载顺序&#xA;&lt;/h3&gt;&lt;p&gt;Config Client 的配置优先级：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;bootstrap.yml&lt;/strong&gt;（配置 Config Server 地址和应用名）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Config Server 返回的远程配置&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;本地的 application.yml&lt;/strong&gt;（作用被远程配置覆盖）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;配置详解&#34;&gt;配置详解&#xA;&lt;/h2&gt;&lt;h3 id=&#34;config-server-配置&#34;&gt;Config Server 配置&#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-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dependency&amp;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:#f92672&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.cloud&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/groupId&amp;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:#f92672&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-config-server&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/artifactId&amp;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:#f92672&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;server&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;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8888&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:#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;cloud&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;config&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;server&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;git&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;uri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;https://github.com/your-repo/config-repo.git&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;search-paths&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;config-files&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;default-label&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;master        &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:#f92672&#34;&gt;timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;                   &lt;span style=&#34;color:#75715e&#34;&gt;# Git 连接超时（秒）&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;force-pull&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;# 拉取失败时强制覆盖本地&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;@SpringBootApplication&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;@EnableConfigServer&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;ConfigServerApplication&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;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        SpringApplication.&lt;span style=&#34;color:#a6e22e&#34;&gt;run&lt;/span&gt;(ConfigServerApplication.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;, args);&#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;h3 id=&#34;config-client-配置&#34;&gt;Config Client 配置&#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;application&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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;my-app&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;cloud&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;config&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;uri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;http://localhost:8888&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;profile&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;dev&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;label&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;master&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;# 失败快速响应（启动时连不上 Config Server 则直接启动失败）&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;fail-fast&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:#f92672&#34;&gt;retry&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;initial-interval&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&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;multiplier&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1.5&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;max-attempts&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;加密配置&#34;&gt;加密配置&#xA;&lt;/h3&gt;&lt;p&gt;Config Server 支持对配置内容加密，有两种方式：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;对称加密&lt;/strong&gt;：设置 &lt;code&gt;encrypt.key=your-secret-key&lt;/code&gt;，然后 POST 到 &lt;code&gt;/encrypt&lt;/code&gt; 端点获取密文&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;非对称加密&lt;/strong&gt;：配置 RSA 密钥对，将公钥给 Config Server，私钥用于解密&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;加密后的配置以 &lt;code&gt;{cipher}&lt;/code&gt; 前缀存储在 Git 中：&lt;/p&gt;&#xA;&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;datasource&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;password&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{cipher}AQB...encrypted-string...&amp;#39;&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;手动刷新逐台刷新&#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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST http://localhost:8080/actuator/refresh&#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;/li&gt;&#xA;&lt;li&gt;分批蓝绿部署&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;全局刷新通过-bus&#34;&gt;全局刷新（通过 Bus）&#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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST http://localhost:8888/actuator/bus-refresh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过消息中间件广播刷新事件，所有订阅的客户端同时刷新。&lt;/p&gt;&#xA;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;graph TD;&#xA;    A[Config Server 接收到刷新请求] --&gt; B[通过 RabbitMQ 发送刷新事件]&#xA;    B --&gt; C[Config Client 接收到刷新事件]&#xA;    C --&gt; D[RefreshScope.refreshAll]&#xA;    D --&gt; E[销毁 @RefreshScope 标记的 Bean]&#xA;    E --&gt; F[重新初始化 Bean]&#xA;    F --&gt; G[配置更新完成]&lt;/pre&gt;&lt;h3 id=&#34;refreshscope-的局限性&#34;&gt;@RefreshScope 的局限性&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;只对标注了 &lt;code&gt;@RefreshScope&lt;/code&gt; 的 Bean 有效，引用了该 Bean 的其他 Bean 不会自动重建&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt; 类必须同时标注 &lt;code&gt;@RefreshScope&lt;/code&gt; 才能刷新&lt;/li&gt;&#xA;&lt;li&gt;静态变量不会随刷新更新&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;排查思路&#34;&gt;排查思路&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;客户端连不上 Config Server&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;bootstrap.yml&lt;/code&gt; 中的 &lt;code&gt;spring.cloud.config.uri&lt;/code&gt; 是否正确&lt;/li&gt;&#xA;&lt;li&gt;检查 Config Server 是否启动、网络是否可达&lt;/li&gt;&#xA;&lt;li&gt;配置 &lt;code&gt;fail-fast: true&lt;/code&gt; 和 &lt;code&gt;retry&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;配置未更新&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Config Client 未添加 &lt;code&gt;@RefreshScope&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;调用 refresh 接口时请求体为空（应为 POST 而非 GET）&lt;/li&gt;&#xA;&lt;li&gt;配置在 Git 中已修改但 Config Server 缓存未刷新——设置 &lt;code&gt;spring.cloud.config.server.git.refresh-rate=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;环境加载错误&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 Git 仓库中的文件名格式：必须为 &lt;code&gt;{application}-{profile}.yml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;default-label&lt;/code&gt; 分支名需要与 Git 仓库匹配&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;检查 &lt;code&gt;encrypt.key&lt;/code&gt; 是否在 Config Server 端正确配置&lt;/li&gt;&#xA;&lt;li&gt;加密的文本首尾是否有 &lt;code&gt;{cipher}&lt;/code&gt; 前缀&lt;/li&gt;&#xA;&lt;li&gt;非对称加密时，确保公钥已在环境变量或文件配置中正确设置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Config Server 性能问题&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Git 仓库过大会拖慢首次加载——使用 &lt;code&gt;spring.cloud.config.server.git.clone-on-start=false&lt;/code&gt;（首次访问时才克隆）&lt;/li&gt;&#xA;&lt;li&gt;每次请求都访问 Git 仓库有性能损耗——使用本地缓存或 &lt;code&gt;basedir&lt;/code&gt; 指向预克隆仓库&lt;/li&gt;&#xA;&lt;li&gt;高并发场景考虑配置强制 &lt;code&gt;skip-ssl-validation&lt;/code&gt; 或使用 SSH 而非 HTTPS 避免证书验证开销&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Spring Cloud Bus</title>
            <link>https://xumf.net/blog/springcloudbus/</link>
            <pubDate>Fri, 05 Jan 2024 13:42:22 +0800</pubDate>
            <guid>https://xumf.net/blog/springcloudbus/</guid>
            <description>&lt;h2 id=&#34;spring-cloud-bus-的核心概念&#34;&gt;Spring Cloud Bus 的核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1什么是-spring-cloud-bus&#34;&gt;（1）什么是 Spring Cloud Bus？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Spring Cloud Bus 是一个分布式事件总线，用于在微服务之间传播状态变化（如配置更新）&lt;/li&gt;&#xA;&lt;li&gt;它基于消息中间件（RabbitMQ、Kafka）实现，解决 Config Server 逐台通知的痛点——没有 Bus 时，配置变更后需要逐一重启或手动调用每个客户端端点的 &lt;code&gt;refresh&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;与 Spring Cloud Config 配合使用是主流场景，但 Bus 本身不依赖 Config——任何需要广播的事件都可以通过 Bus 传播&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2spring-cloud-bus-的组成&#34;&gt;（2）Spring Cloud Bus 的组成&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;消息中间件&lt;/strong&gt;：RabbitMQ 或 Kafka，负责传递事件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;事件生产者&lt;/strong&gt;：Config Server 或其他微服务，发送事件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;事件消费者&lt;/strong&gt;：Config Client 或其他微服务，接收事件并执行相应操作&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3spring-cloud-bus-的特点&#34;&gt;（3）Spring Cloud Bus 的特点&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;全局配置刷新：通过 &lt;code&gt;/actuator/bus-refresh&lt;/code&gt; 端点触发全局配置刷新&lt;/li&gt;&#xA;&lt;li&gt;服务状态同步：通过事件传播实现服务状态同步&lt;/li&gt;&#xA;&lt;li&gt;多消息中间件支持：支持 RabbitMQ 和 Kafka&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;定点通知&lt;/strong&gt;：支持指定某个或某几个服务实例刷新（&lt;code&gt;/actuator/bus-refresh/{destination}&lt;/code&gt;），避免全量广播&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-的工作原理&#34;&gt;Spring Cloud Bus 的工作原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1事件传播流程&#34;&gt;（1）事件传播流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;事件生产者（如 Config Server）发送事件到消息中间件&lt;/li&gt;&#xA;&lt;li&gt;消息中间件将事件广播给所有订阅该队列的消费者&lt;/li&gt;&#xA;&lt;li&gt;事件消费者接收到事件并执行相应操作&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;关键：每个 Bus 客户端启动时会在消息中间件中创建自己的唯一队列（基于 &lt;code&gt;spring.cloud.bus.id&lt;/code&gt;），Bus 通过这个队列实现定点通知——&lt;code&gt;/bus-refresh/user-service:**&lt;/code&gt; 只会发送给 service ID 为 user-service 的实例。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2全局配置刷新流程&#34;&gt;（2）全局配置刷新流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;管理员调用 POST &lt;code&gt;/actuator/bus-refresh&lt;/code&gt;（向任意一个 Bus 客户端请求即可——它会通过消息中间件广播给所有实例）&lt;/li&gt;&#xA;&lt;li&gt;该客户端发布 &lt;code&gt;RefreshRemoteApplicationEvent&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;消息中间件广播该事件&lt;/li&gt;&#xA;&lt;li&gt;所有 Config Client 监听到事件，调用 &lt;code&gt;ContextRefresher.refresh()&lt;/code&gt; → &lt;code&gt;RefreshScope.refreshAll()&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;标记了 &lt;code&gt;@RefreshScope&lt;/code&gt; 的 Bean 被销毁并重新创建，加载新配置&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-的配置&#34;&gt;Spring Cloud Bus 的配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1rabbitmq-配置&#34;&gt;（1）RabbitMQ 配置&#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;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;host&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;localhost&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;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5672&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;username&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;guest&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;password&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;guest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2kafka-配置&#34;&gt;（2）Kafka 配置&#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;kafka&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;bootstrap-servers&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;localhost:9092&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;consumer&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;group-id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;my-group&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3添加依赖&#34;&gt;（3）添加依赖&#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-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dependency&amp;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:#f92672&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.cloud&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/groupId&amp;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:#f92672&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-starter-bus-amqp&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- RabbitMQ --&amp;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;&amp;lt;!-- 或 --&amp;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;&amp;lt;!-- &amp;lt;artifactId&amp;gt;spring-cloud-starter-bus-kafka&amp;lt;/artifactId&amp;gt; --&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Kafka --&amp;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:#f92672&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;4暴露-actuator-端点&#34;&gt;（4）暴露 Actuator 端点&#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;management&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;endpoints&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;web&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;exposure&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;include&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;bus-refresh&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;spring-cloud-bus-的使用场景&#34;&gt;Spring Cloud Bus 的使用场景&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1全局配置刷新&#34;&gt;（1）全局配置刷新&#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-bash&#34; data-lang=&#34;bash&#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;curl -X POST http://localhost:8888/actuator/bus-refresh&#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;# 定点刷新（只刷新 user-service）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST http://localhost:8888/actuator/bus-refresh/user-service:**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2自定义事件&#34;&gt;（2）自定义事件&#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;&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; ApplicationEventPublisher publisher;&#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;sendCustomEvent&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    publisher.&lt;span style=&#34;color:#a6e22e&#34;&gt;publishEvent&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyCustomEvent(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-data&amp;#34;&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;// 接收自定义事件&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;@EventListener&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;handleCustomEvent&lt;/span&gt;(MyCustomEvent event) {&#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;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：自定义事件必须继承 &lt;code&gt;RemoteApplicationEvent&lt;/code&gt; 才能通过 Bus 传播到其他服务节点，否则只会在本地发布。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3指定服务刷新的场景&#34;&gt;（3）指定服务刷新的场景&#xA;&lt;/h3&gt;&lt;p&gt;当集群中不同服务配置不同时，全量刷新可能造成混乱。定点刷新适用于：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;灰度配置发布：只刷新新版本的服务实例&lt;/li&gt;&#xA;&lt;li&gt;分批部署：一组一组刷新，观察无问题后再继续&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-源码概览&#34;&gt;Spring Cloud Bus 源码概览&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1busrefreshendpoint&#34;&gt;（1）BusRefreshEndpoint&#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;@Endpoint&lt;/span&gt;(id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bus-refresh&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;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BusRefreshEndpoint&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:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationEventPublisher publisher;&#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:#a6e22e&#34;&gt;BusRefreshEndpoint&lt;/span&gt;(ApplicationEventPublisher publisher) {&#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;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;publisher&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; publisher;&#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;@WriteOperation&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;refresh&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        publisher.&lt;span style=&#34;color:#a6e22e&#34;&gt;publishEvent&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RefreshRemoteApplicationEvent(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&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;h3 id=&#34;2refreshremoteapplicationevent&#34;&gt;（2）RefreshRemoteApplicationEvent&#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;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshRemoteApplicationEvent&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; RemoteApplicationEvent {&#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:#a6e22e&#34;&gt;RefreshRemoteApplicationEvent&lt;/span&gt;(Object source, String originService, String destinationService) {&#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;super&lt;/span&gt;(source, originService, destinationService);&#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;destinationService&lt;/code&gt; 参数用于定点通知：&lt;code&gt;null&lt;/code&gt; 表示广播给所有服务，指定值（如 &lt;code&gt;user-service:**&lt;/code&gt;）则只发送给匹配的实例。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3refreshlistener&#34;&gt;（3）RefreshListener&#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;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshListener&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; ApplicationListener&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;RefreshRemoteApplicationEvent&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;&#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; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; RefreshScope refreshScope;&#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:#a6e22e&#34;&gt;RefreshListener&lt;/span&gt;(RefreshScope refreshScope) {&#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;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;refreshScope&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; refreshScope;&#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;@Override&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;onApplicationEvent&lt;/span&gt;(RefreshRemoteApplicationEvent event) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        refreshScope.&lt;span style=&#34;color:#a6e22e&#34;&gt;refreshAll&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;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Bugs 刷新后配置未生效&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;@RefreshScope&lt;/code&gt; 是否标注在使用配置的 Bean 上（注意：@RefreshScope 只对加了该注解的 Bean 有效，其依赖的其他 Bean 不会重建）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt; 的类只需标注 &lt;code&gt;@RefreshScope&lt;/code&gt; 即可刷新，但已经在使用的 Bean 不会自动重新注入——需要确保引用方也标注 @RefreshScope&lt;/li&gt;&#xA;&lt;li&gt;检查 Control Bus 端口（&lt;code&gt;spring.cloud.bus.id&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;事件未传播到其他服务&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查所有服务是否连接到同一个消息中间件实例（不同的 RabbitMQ vhost 或 Kafka topic 会导致隔离）&lt;/li&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;spring.cloud.bus.destination&lt;/code&gt; 配置是否一致（默认 &lt;code&gt;springCloudBus&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;Bus refresh 导致启动过慢&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Bus 客户端启动时会连接到消息中间件，如果中间件不可用，启动会卡住。可通过 &lt;code&gt;spring.cloud.bus.enabled=false&lt;/code&gt; 禁用非必要实例的 Bus 功能&lt;/li&gt;&#xA;&lt;li&gt;建议配置 &lt;code&gt;spring.cloud.bus.env.enabled=true&lt;/code&gt;（默认开启），允许 Bus 端点只在特定 profile 下启用&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;RabbitMQ 配置正确但连接失败&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查防火墙和端口（5672 是 AMQP 端口，15672 是管理控制台——两者不要混淆）&lt;/li&gt;&#xA;&lt;li&gt;验证 RabbitMQ 的 vhost 和用户权限&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Ribbon</title>
            <link>https://xumf.net/blog/ribbon/</link>
            <pubDate>Wed, 19 Apr 2023 21:09:25 +0800</pubDate>
            <guid>https://xumf.net/blog/ribbon/</guid>
            <description>&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Ribbon 已进入&lt;strong&gt;维护状态&lt;/strong&gt;（Netflix 不再积极开发）。从 Spring Cloud 2020.0.x（Ilford）开始，官方推荐使用 &lt;strong&gt;Spring Cloud LoadBalancer&lt;/strong&gt; 作为替代。新项目直接使用 LoadBalancer，旧项目建议逐步迁移。本文内容基于 Ribbon 2.x 版本。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;核心概念&#34;&gt;核心概念&#xA;&lt;/h2&gt;&lt;p&gt;Ribbon 是 Netflix 开源的客户端负载均衡器，核心功能：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;负载均衡&lt;/strong&gt;：从多个服务实例中选择一个处理请求&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;故障转移&lt;/strong&gt;：选择的实例不可用时自动重试其他实例&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重试机制&lt;/strong&gt;：支持配置重试次数和超时&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;关键设计点：Ribbon 是&lt;strong&gt;客户端负载均衡&lt;/strong&gt;，与 Nginx 等&lt;strong&gt;服务端负载均衡&lt;/strong&gt;不同：&lt;/p&gt;&#xA;&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;客户端负载均衡（Ribbon）&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;服务端负载均衡（Nginx）&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;位置&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;配置 upstream&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;需在 upstream 配置&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;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;工作原理&#34;&gt;工作原理&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务发现&lt;/strong&gt;：Ribbon 从注册中心（如 Eureka）获取服务实例列表，并动态更新&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;负载均衡&lt;/strong&gt;：根据配置的策略从列表中选择一个实例&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;故障转移&lt;/strong&gt;：不可用时自动重试其他实例&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;请求分发&lt;/strong&gt;：将请求分发到选定实例，处理响应&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;完整请求流程&#34;&gt;完整请求流程&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Client Request&#xA;    → RestTemplate/Feign (URL: http://service-name/endpoint)&#xA;    → RibbonLoadBalancerClient.choose(&amp;#34;service-name&amp;#34;)&#xA;        → DynamicServerListLoadBalancer.getServerList()&#xA;            → EurekaClient.getInstancesByVipAddress()&#xA;        → IRule.choose(serverList)&#xA;            → 选择策略: 轮询/随机/加权...&#xA;    → 发送 HTTP 请求到选定实例&#xA;    → 失败时: RetryHandler 重试其他实例&#xA;    → 返回响应&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;负载均衡策略详解&#34;&gt;负载均衡策略详解&#xA;&lt;/h2&gt;&lt;p&gt;Ribbon 提供 7 种内置策略：&lt;/p&gt;&#xA;&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;RoundRobinRule&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;RandomRule&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;WeightedResponseTimeRule&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;ZoneAvoidanceRule&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;BestAvailableRule&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;RetryRule&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;AvailabilityFilteringRule&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;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;配置方式&#34;&gt;配置方式&#xA;&lt;/h2&gt;&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-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;ribbon&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;ConnectTimeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&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;ReadTimeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3000&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;MaxAutoRetries&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&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:#f92672&#34;&gt;MaxAutoRetriesNextServer&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&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:#f92672&#34;&gt;OkToRetryOnAllOperations&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 是否所有操作都重试&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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-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;service-name&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;ribbon&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;NFLoadBalancerRuleClassName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;com.netflix.loadbalancer.RoundRobinRule&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;MaxAutoRetries&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&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;MaxAutoRetriesNextServer&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&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;ConnectTimeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&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;ReadTimeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;@RibbonClient&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;service-name&amp;#34;&lt;/span&gt;, configuration &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; MyRibbonConfig.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&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;MyRibbonConfig&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; IRule &lt;span style=&#34;color:#a6e22e&#34;&gt;ribbonRule&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; RandomRule();&#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; RetryHandler &lt;span style=&#34;color:#a6e22e&#34;&gt;retryHandler&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;// 参数: maxRetriesOnSameServer, maxRetriesOnNextServer, okToRetryOnAllOperations&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; DefaultLoadBalancerRetryHandler(3, 1, &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;    }&#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;strong&gt;注意&lt;/strong&gt;：使用 &lt;code&gt;@RibbonClient&lt;/code&gt; 时，配置类不能被 &lt;code&gt;@ComponentScan&lt;/code&gt; 扫描到（否则成为全局配置），建议放在启动类所在包之外。&lt;/p&gt;&#xA;&lt;h2 id=&#34;使用场景&#34;&gt;使用场景&#xA;&lt;/h2&gt;&lt;h3 id=&#34;与-resttemplate-集成&#34;&gt;与 RestTemplate 集成&#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;@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:#a6e22e&#34;&gt;@LoadBalanced&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; RestTemplate &lt;span style=&#34;color:#a6e22e&#34;&gt;restTemplate&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; RestTemplate();&#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;// 调用时直接用服务名，Ribbon 自动解析为实例 IP:PORT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;String response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; restTemplate.&lt;span style=&#34;color:#a6e22e&#34;&gt;getForObject&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://service-name/endpoint&amp;#34;&lt;/span&gt;, String.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;与-feign-集成&#34;&gt;与 Feign 集成&#xA;&lt;/h3&gt;&lt;p&gt;Feign 默认集成 Ribbon，无需额外配置：&lt;/p&gt;&#xA;&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;@FeignClient&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;service-name&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;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyFeignClient&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;@GetMapping&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/endpoint&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String &lt;span style=&#34;color:#a6e22e&#34;&gt;getResponse&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;iloadbalancer-接口&#34;&gt;ILoadBalancer 接口&#xA;&lt;/h3&gt;&lt;p&gt;Ribbon 的核心接口是 &lt;code&gt;ILoadBalancer&lt;/code&gt;，负责管理服务实例列表：&lt;/p&gt;&#xA;&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;ILoadBalancer&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;addServers&lt;/span&gt;(List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Server&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; newServers);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Server &lt;span style=&#34;color:#a6e22e&#34;&gt;chooseServer&lt;/span&gt;(Object key);     &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;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;markServerDown&lt;/span&gt;(Server server);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Server&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getServerList&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt; availableOnly);&#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;markServerDown&lt;/span&gt;(Server server);&#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;DynamicServerListLoadBalancer&lt;/code&gt; 通过 &lt;code&gt;ServerListUpdater&lt;/code&gt; 定时从注册中心拉取最新实例：&lt;/p&gt;&#xA;&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;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DynamicServerListLoadBalancer&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; Server&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; BaseLoadBalancer {&#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; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ServerList&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; serverList;&#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; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ServerListUpdater serverListUpdater;&#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;protected&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;updateListOfServers&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; servers &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; serverList.&lt;span style=&#34;color:#a6e22e&#34;&gt;getUpdatedListOfServers&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        setServersList(servers);&#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;h3 id=&#34;irule-负载均衡策略接口&#34;&gt;IRule 负载均衡策略接口&#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;IRule&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Server &lt;span style=&#34;color:#a6e22e&#34;&gt;choose&lt;/span&gt;(Object key);&#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;setLoadBalancer&lt;/span&gt;(ILoadBalancer lb);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ILoadBalancer &lt;span style=&#34;color:#a6e22e&#34;&gt;getLoadBalancer&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;h3 id=&#34;从-eureka-获取实例&#34;&gt;从 Eureka 获取实例&#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;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DiscoveryEnabledNIWSServerList&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; AbstractServerList&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;DiscoveryEnabledServer&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;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; EurekaClient eurekaClient;&#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; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String serviceId;&#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;private&lt;/span&gt; List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;DiscoveryEnabledServer&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;obtainServersViaDiscovery&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;InstanceInfo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; listOfInstanceInfo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; eurekaClient.&lt;span style=&#34;color:#a6e22e&#34;&gt;getInstancesByVipAddress&lt;/span&gt;(serviceId, &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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;for&lt;/span&gt; (InstanceInfo instanceInfo : listOfInstanceInfo) {&#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;if&lt;/span&gt; (instanceInfo.&lt;span style=&#34;color:#a6e22e&#34;&gt;getStatus&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; InstanceInfo.&lt;span style=&#34;color:#a6e22e&#34;&gt;InstanceStatus&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;UP&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                serverList.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DiscoveryEnabledServer(instanceInfo, &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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;            }&#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;return&lt;/span&gt; serverList;&#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;迁移到-spring-cloud-loadbalancer&#34;&gt;迁移到 Spring Cloud LoadBalancer&#xA;&lt;/h2&gt;&lt;p&gt;从 Spring Cloud 2020.0.x 开始，Ribbon 被 LoadBalancer 取代。迁移要点：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;移除 Ribbon 依赖&lt;/strong&gt;：删除 &lt;code&gt;spring-cloud-starter-netflix-ribbon&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;添加 LoadBalancer 依赖&lt;/strong&gt;：&lt;code&gt;spring-cloud-starter-loadbalancer&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;接口变化&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ILoadBalancer&lt;/code&gt; → &lt;code&gt;ReactiveLoadBalancer&lt;/code&gt; / &lt;code&gt;BlockingLoadBalancerClient&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;IRule&lt;/code&gt; → &lt;code&gt;ReactiveLoadBalancer&lt;/code&gt; 实现（如 &lt;code&gt;RoundRobinLoadBalancer&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@RibbonClient&lt;/code&gt; → 无直接等价，通过 &lt;code&gt;LoadBalancerClient&lt;/code&gt; 配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置变化&lt;/strong&gt;：&lt;code&gt;service-name.ribbon.*&lt;/code&gt; → &lt;code&gt;spring.cloud.loadbalancer.*&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&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:#75715e&#34;&gt;# LoadBalancer 配置示例&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;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;cloud&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;loadbalancer&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;retry&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;enabled&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:#f92672&#34;&gt;health-check&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;interval&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30s&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;configurations&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;health-check&lt;/span&gt; &lt;span style=&#34;color:#75715e&#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;负载均衡不生效（总是访问同一个实例）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;确认 &lt;code&gt;@LoadBalanced&lt;/code&gt; 注解已在 RestTemplate Bean 上&lt;/li&gt;&#xA;&lt;li&gt;检查服务名解析：&lt;code&gt;http://service-name/&lt;/code&gt; 中的 service-name 是否与注册中心的服务名一致&lt;/li&gt;&#xA;&lt;li&gt;Ribbon 默认使用 ZoneAvoidanceRule，如果所有实例在同一 zone，行为类似轮询&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;检查 &lt;code&gt;ServerListRefreshInterval&lt;/code&gt;（默认 30 秒）&lt;/li&gt;&#xA;&lt;li&gt;检查 Eureka Client 的 &lt;code&gt;eureka.client.registryFetchIntervalSeconds&lt;/code&gt;（默认 30 秒）&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;Ribbon 本身不触发重试——需要配合 Spring Retry（需引入 &lt;code&gt;spring-retry&lt;/code&gt; 依赖）&lt;/li&gt;&#xA;&lt;li&gt;只有 &lt;code&gt;@LoadBalanced&lt;/code&gt; 的 RestTemplate 或 Feign 客户端才会触发 Ribbon 重试&lt;/li&gt;&#xA;&lt;li&gt;确保 &lt;code&gt;MaxAutoRetries&lt;/code&gt; 和 &lt;code&gt;MaxAutoRetriesNextServer&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;引入 LoadBalancer 后 Ribbon 失效&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Spring Cloud 2020.0.x 默认禁用了 Ribbon，如果仍想使用需要设置 &lt;code&gt;spring.cloud.loadbalancer.ribbon.enabled=true&lt;/code&gt;（但已不推荐）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Nacos</title>
            <link>https://xumf.net/blog/nacos/</link>
            <pubDate>Tue, 03 May 2022 20:54:29 +0800</pubDate>
            <guid>https://xumf.net/blog/nacos/</guid>
            <description>&lt;h2 id=&#34;一nacos-核心概念&#34;&gt;一、Nacos 核心概念&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;是什么？&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Nacos（Dynamic Naming and Configuration Server）是阿里开源的&lt;strong&gt;服务发现+配置管理+服务治理平台&lt;/strong&gt;，核心功能：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务发现与健康监测&lt;/strong&gt;：服务注册、心跳机制、DNS 查询&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;动态配置管理&lt;/strong&gt;：配置发布、监听、版本管理&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;动态 DNS&lt;/strong&gt;：基于权重的路由、地域就近访问&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务元数据管理&lt;/strong&gt;：支持应用/版本/环境等元数据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;关键特性&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;双模式&lt;/strong&gt;：支持 CP（强一致性、如配置管理）和 AP（高可用，如服务发现）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置实时推送&lt;/strong&gt;：基于长轮询（减少无效请求）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;生态兼容&lt;/strong&gt;：无缝集成 Spring Cloud、Dubbo、Kubernetes&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;二核心架构与原理&#34;&gt;二、核心架构与原理&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务注册与发现流程&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;注册&lt;/strong&gt;：服务启动时向 Nacos Server 发送注册请求（HTTP/gRPC）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;心跳&lt;/strong&gt;：客户端定期发送心跳（默认5秒），超时（15秒）标记为不健康，30秒后剔除&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;发现&lt;/strong&gt;：消费者通过订阅机制获取服务列表，本地缓存+增量更新&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置管理机制&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;发布配置&lt;/strong&gt;：通过控制台/API发布配置，存储于 Derby 或 MySQL&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监听配置&lt;/strong&gt;：客户端长轮询（默认30秒），服务端 Hold 住请求，配置变更立即返回&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;历史版本&lt;/strong&gt;：支持配置回滚和版本对比&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;一致性协议&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;CP 模式&lt;/strong&gt;：使用 Raft 协议（配置管理场景）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;AP 模式&lt;/strong&gt;：自研 &lt;a class=&#34;link&#34; href=&#34;https://nacos.io/zh-cn/blog/nacos-distro-mechanism/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Distro 协议&lt;/a&gt;（服务发现场景，最终一致性）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三重要知识点&#34;&gt;三、重要知识点&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos vs Eureka vs Zookeeper？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Eureka&lt;/strong&gt;：AP 设计，适合服务发现，但功能单一&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Zookeeper&lt;/strong&gt;：CP 设计，强一致性，但写性能低&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos&lt;/strong&gt;：AP/CP 可切换，集成服务发现+配置管理，生态更全面&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;长轮询如何实现配置实时推送？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;客户端发起查询请求，若配置无变化，服务端 Hold 请求至超时（默认30秒）或期间配置变更立即返回&lt;/li&gt;&#xA;&lt;li&gt;对比传统轮询：减少无效请求，提升实时性&lt;/li&gt;&#xA;&lt;li&gt;对比 WebSocket：长轮询服务端实现更简单，但存在30秒最大延迟（非实时配置场景选长轮询即可，实时性要求极高场景考虑 gRPC 流式推送）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos 集群如何保证数据一致性？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Distro 模式（AP 模式）&lt;/strong&gt;：每个节点负责部分数据，通过异步复制保证最终一致性。写入时先写本地，再异步复制到其他节点；读取时可能读到旧数据，但通常可接受（服务发现场景对一致性要求不高）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Raft 协议（CP 模式）&lt;/strong&gt;：选举 Leader，多数节点写成功才返回。适用于配置管理——配置错了影响面大，宁可不更新也不能不一致。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos 2.0 升级了哪些内容？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;通信层优化&lt;/strong&gt;：gRPC 替代 HTTP，减少连接数（1.x 每个客户端与 server 维持多个 HTTP 长连接，2.0 全复用为一条 gRPC 连接）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;长连接增强&lt;/strong&gt;：支持服务端主动推送，降低延迟&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;性能提升&lt;/strong&gt;：支撑百万级服务实例&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;如何实现配置灰度发布？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通过 &lt;strong&gt;Data ID 或 Group&lt;/strong&gt; 分组，结合 Spring Cloud 的 &lt;code&gt;@RefreshScope&lt;/code&gt; 或监听 &lt;code&gt;ConfigChangeEvent&lt;/code&gt; 实现部分实例更新&lt;/li&gt;&#xA;&lt;li&gt;更优雅的方式：使用 Nacos 的 Beta 发布功能——指定目标 IP 列表，只有命中 IP 的客户端拉取到灰度配置。验证无误后再全量发布。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;四实战场景与排查思路&#34;&gt;四、实战场景与排查思路&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务注册失败常见原因&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;网络不通：检查 Nacos Server 地址和端口（telnet 或 nc 测试连通性）&lt;/li&gt;&#xA;&lt;li&gt;版本冲突：Spring Cloud Alibaba 与 Nacos 版本不兼容 → 参考官方版本对应表&lt;/li&gt;&#xA;&lt;li&gt;命名空间/Group 配置错误：客户端 &lt;code&gt;namespace&lt;/code&gt; 和 &lt;code&gt;group&lt;/code&gt; 须与服务端一致，命名空间为空时默认使用 public&lt;/li&gt;&#xA;&lt;li&gt;防火墙/安全组拦截：gRPC 端口（9848/9849）需额外开放&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置不生效排查步骤&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查控制台配置是否发布成功（Data ID、Group、命名空间与客户端代码匹配）&lt;/li&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;@RefreshScope&lt;/code&gt; 是否加在正确的位置——标注在 @Configuration 类上可能导致整个类重新创建，注意副作用&lt;/li&gt;&#xA;&lt;li&gt;查看日志：&lt;code&gt;com.alibaba.nacos.client.config.listener&lt;/code&gt; 包日志是否有监听异常&lt;/li&gt;&#xA;&lt;li&gt;长轮询超时确认：查看请求日志中 HTTP 状态码是否为 200（非 304 表示配置变更）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos 集群部署注意事项&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;至少 3 个节点形成 Raft 选举（节点数建议奇数，避免脑裂）&lt;/li&gt;&#xA;&lt;li&gt;使用 MySQL 作为外部存储（Derby 仅适合单机测试——集群模式下不使用 MySQL 会导致各节点数据不一致）&lt;/li&gt;&#xA;&lt;li&gt;所有节点配置文件中的 &lt;code&gt;cluster.conf&lt;/code&gt; 必须包含所有节点地址&lt;/li&gt;&#xA;&lt;li&gt;通过 Nginx 做负载均衡时，gRPC 长连接需要配置 &lt;code&gt;upstream&lt;/code&gt; 为 &lt;code&gt;ip_hash&lt;/code&gt; 或使用 &lt;code&gt;nginx-stream&lt;/code&gt; 模块&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五高级话题&#34;&gt;五、高级话题&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Nacos-Sync 应用&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;跨注册中心同步（如 Kubernetes Service 到 Nacos、Eureka 迁移到 Nacos）&lt;/li&gt;&#xA;&lt;li&gt;本质是事件监听+双向同步，注意循环同步问题（A→B→A 死循环），Nacos-Sync 通过记录同步来源避免&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;安全控制&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;开启鉴权：&lt;code&gt;nacos.core.auth.enabled=true&lt;/code&gt;，配置自定义用户角色&lt;/li&gt;&#xA;&lt;li&gt;重要：Nacos 2.2.3 之前默认鉴权不开启，且密钥为硬编码，务必修改 &lt;code&gt;nacos.core.auth.plugin.nacos.token.secret.key&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;双活部署&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;多数据中心通过 Nacos-Sync 同步数据，结合 DNS 实现流量切换&lt;/li&gt;&#xA;&lt;li&gt;注意：跨地域同步存在网络延迟，配置变更可能在数秒后才能传播到异地——不要依赖 Nacos 跨地域强一致&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Hystrix</title>
            <link>https://xumf.net/blog/hystrix/</link>
            <pubDate>Wed, 22 May 2019 15:49:23 +0800</pubDate>
            <guid>https://xumf.net/blog/hystrix/</guid>
            <description>&lt;h3 id=&#34;功能&#34;&gt;功能&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;服务熔断&lt;/li&gt;&#xA;&lt;li&gt;服务降级&lt;/li&gt;&#xA;&lt;li&gt;资源隔离&lt;/li&gt;&#xA;&lt;li&gt;请求缓存&lt;/li&gt;&#xA;&lt;li&gt;请求合并&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;核心思想&#34;&gt;核心思想&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;防止服务雪崩&#xA;当一个服务发生故障时，避免故障扩散到整个系统&lt;/li&gt;&#xA;&lt;li&gt;快速失败&#xA;通过熔断机制快速失败。避免资源耗尽。&lt;/li&gt;&#xA;&lt;li&gt;优雅降级&#xA;在服务不可用的时候，提供备用方案（Fallback）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;熔断器circuit-breaker&#34;&gt;熔断器（Circuit Breaker）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;原理&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当服务的容错率超过阈值时，熔断器会被打开，后续请求会直接失败，不再调用目标服务&lt;/li&gt;&#xA;&lt;li&gt;熔断器打开一段时间后，会进入半打开状态，尝试恢复服务&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;关键参数&#xA;&lt;ul&gt;&#xA;&lt;li&gt;circuitBreaker.requestVolumeThreshold：触发熔断器需要最小请求数&lt;/li&gt;&#xA;&lt;li&gt;circuitBreaker.errorThresholdPercentage：错误率阈值（默认为50%）&lt;/li&gt;&#xA;&lt;li&gt;circuitBreaker.sleepWindowInMilliseconds：熔断器打开后的休眠时间（默认为5秒）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;资源隔离&#34;&gt;资源隔离&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;线程池隔离&#xA;&lt;ul&gt;&#xA;&lt;li&gt;每个服务调用使用独立的线程池，避免资源竞争&lt;/li&gt;&#xA;&lt;li&gt;通过 HystrixThreadPoolKey 配置线程池&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;信号量隔离&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用信号量限制并发数，适用于轻量级调用（执行时间短的任务）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;服务降级&#34;&gt;服务降级&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;原理&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当服务调用失败或者熔断器打开时，执行降级逻辑&lt;/li&gt;&#xA;&lt;li&gt;降级逻辑可以是返回默认值、调用备用服务等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;实现&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通过 HystrixCommand(fallbackMethod = &amp;ldquo;fallbackMethod&amp;rdquo;) 指定降级方法&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;请求缓存&#34;&gt;请求缓存&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;原理&#xA;&lt;ul&gt;&#xA;&lt;li&gt;对相同请求参数，Hystrix 可以缓存结果，减少重复调用&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;实现&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用 @CacheResult 和 @CacheKey 注解&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;请求合并&#34;&gt;请求合并&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;原理&#xA;&lt;ul&gt;&#xA;&lt;li&gt;将多个请求合并为一个批量请求，减少网络开销&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;实现&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用 @HystrixCollapser 注解&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;工作流程&#34;&gt;工作流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;请求进入：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;请求被 Hystrix 拦截&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;检查熔断器状态&#xA;&lt;ol&gt;&#xA;&lt;li&gt;如果熔断器打开，直接执行降级逻辑&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;资源隔离&#xA;&lt;ol&gt;&#xA;&lt;li&gt;根据配置选择线程池隔离或信号量隔离&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;执行目标服务&#xA;&lt;ol&gt;&#xA;&lt;li&gt;调用目标服务，记录成功或者失败&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;更新熔断器状态&#xA;&lt;ol&gt;&#xA;&lt;li&gt;根据调用结果更新熔断器状态&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;执行降级逻辑&#xA;&lt;ol&gt;&#xA;&lt;li&gt;如果调用失败或者熔断器打开，执行降级逻辑&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;返回结果&#xA;&lt;ol&gt;&#xA;&lt;li&gt;返回调用结果或者降级结果&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;sequenceDiagram&#xA;    participant Client as 客户端&#xA;    participant Hystrix as Hystrix&#xA;    participant TargetService as 目标服务&#xA;    participant Fallback as 降级逻辑&#xA;&#xA;    Client-&gt;&gt;Hystrix: 1. 发起请求&#xA;    Hystrix-&gt;&gt;Hystrix: 2. 检查熔断器状态&#xA;    alt 熔断器关闭&#xA;        Hystrix-&gt;&gt;Hystrix: 3. 资源隔离（线程池/信号量）&#xA;        Hystrix-&gt;&gt;TargetService: 4. 调用目标服务&#xA;        TargetService--&gt;&gt;Hystrix: 5. 返回结果&#xA;        Hystrix-&gt;&gt;Hystrix: 6. 更新熔断器状态&#xA;        alt 调用成功&#xA;            Hystrix--&gt;&gt;Client: 7. 返回结果&#xA;        else 调用失败&#xA;            Hystrix-&gt;&gt;Fallback: 8. 执行降级逻辑&#xA;            Fallback--&gt;&gt;Hystrix: 9. 返回降级结果&#xA;            Hystrix--&gt;&gt;Client: 10. 返回降级结果&#xA;        end&#xA;    else 熔断器打开&#xA;        Hystrix-&gt;&gt;Fallback: 11. 执行降级逻辑&#xA;        Fallback--&gt;&gt;Hystrix: 12. 返回降级结果&#xA;        Hystrix--&gt;&gt;Client: 13. 返回降级结果&#xA;    end&lt;/pre&gt;&lt;h3 id=&#34;底层原理&#34;&gt;底层原理&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;熔断器实现&#xA;&lt;ol&gt;&#xA;&lt;li&gt;状态机&#xA;&lt;ol&gt;&#xA;&lt;li&gt;熔断器有三种状态：CLOSED （关闭）、OPEN（打开）、HALF_OPEN（半开）&lt;/li&gt;&#xA;&lt;li&gt;状态转换基于容错率和请求量&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;滑动窗口&#xA;&lt;ol&gt;&#xA;&lt;li&gt;使用滑动窗口统计最近一段时间的请求成功率和错误率&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;线程池隔离&#xA;&lt;ol&gt;&#xA;&lt;li&gt;线程池管理&#xA;&lt;ol&gt;&#xA;&lt;li&gt;每个服务调用使用独立的线程池，避免资源竞争&lt;/li&gt;&#xA;&lt;li&gt;线程池大小通过 **coreSize **和 **maxSize **配置。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;队列管理&#xA;&lt;ol&gt;&#xA;&lt;li&gt;使用有界队列（&lt;strong&gt;BlockingQueue&lt;/strong&gt;）控制请求排队&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;信号量隔离&#xA;&lt;ol&gt;&#xA;&lt;li&gt;信号量机制&#xA;&lt;ol&gt;&#xA;&lt;li&gt;使用 **Semaphore **控制并发请求书&lt;/li&gt;&#xA;&lt;li&gt;适用于轻量级调用，减少线程切换开销&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;请求缓存&#xA;&lt;ol&gt;&#xA;&lt;li&gt;缓存实现&#xA;&lt;ol&gt;&#xA;&lt;li&gt;使用 &lt;strong&gt;ConcurrentHashMap&lt;/strong&gt; 存储缓存结果&lt;/li&gt;&#xA;&lt;li&gt;通过 &lt;strong&gt;@CacheKey&lt;/strong&gt; 指定缓存键&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;请求合并&#xA;&lt;ol&gt;&#xA;&lt;li&gt;合并实现&#xA;&lt;ol&gt;&#xA;&lt;li&gt;使用 &lt;strong&gt;BatchCommand&lt;/strong&gt; 将多个请求合并为一个批量请求&lt;/li&gt;&#xA;&lt;li&gt;通过 &lt;strong&gt;@HystrixCollapser&lt;/strong&gt; 配置合并规则&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;img alt=&#34;image&#34; loading=&#34;lazy&#34; sizes=&#34;(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px&#34; src=&#34;images/NHBaLoW_AxpSCXjKfL2ffJvynFlMnp8I9_-xcX-SxY8.jpg&#34;&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>Feign</title>
            <link>https://xumf.net/blog/feign/</link>
            <pubDate>Fri, 15 Jun 2018 15:43:54 +0800</pubDate>
            <guid>https://xumf.net/blog/feign/</guid>
            <description>&lt;h2 id=&#34;什么是feign&#34;&gt;什么是Feign&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 是 Netflix 开源的声明式 HTTP 客户端，用于简化 RESTful 服务的调用&lt;/li&gt;&#xA;&lt;li&gt;通过定义接口和注解，Feign 可以自动生成HTTP请求的实现&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;特点&#34;&gt;特点&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;声明式 API ：通过接口注解定义 HTTP 请求，无需手动编写 HTTP 客户端代码&lt;/li&gt;&#xA;&lt;li&gt;集成 Ribbon ：默认集成 Ribbon ，支持客户端负载均衡&lt;/li&gt;&#xA;&lt;li&gt;集成 Hystrix ：支持熔断和降级机制&lt;/li&gt;&#xA;&lt;li&gt;可扩展性：支持自定义编码器、解码器和拦截器&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;工作原理&#34;&gt;工作原理&#xA;&lt;/h2&gt;&lt;h2 id=&#34;1接口定义&#34;&gt;（1）接口定义&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;使用 @FeignClient 注解定义 Feign 客户端接口&lt;/li&gt;&#xA;&lt;li&gt;通过方法注解（如 &lt;strong&gt;@GetMapping&lt;/strong&gt;、&lt;strong&gt;@PostMapping&lt;/strong&gt;）定义 HTTP 请求&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2动态代理&#34;&gt;（2）动态代理&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 通过动态代理技术生成接口的实现类&lt;/li&gt;&#xA;&lt;li&gt;在运行时，Feign 会将方法调用转换为 Http 请求&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3请求处理&#34;&gt;（3）请求处理&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 根据接口定义生成 HTTP 请求，并通过 Ribbon 进行负载均衡&lt;/li&gt;&#xA;&lt;li&gt;请求结果通过解码器为 Java 对象&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4集成-ribbon-和-hystrix&#34;&gt;（4）集成 Ribbon 和 Hystrix&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 默认集成了 Ribbon，支持客户端负载均衡&lt;/li&gt;&#xA;&lt;li&gt;通过配置可以启用 Hystrix，实现熔断和降级&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;feign-的配置&#34;&gt;Feign 的配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1基本配置&#34;&gt;（1）基本配置&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;使用 @FeignClient 注解定义 Feign 客户端：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;@FeignClient&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;service-name&amp;#34;&lt;/span&gt;, url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8080&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;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyFeignClient&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;@GetMapping&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/endpoint&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String &lt;span style=&#34;color:#a6e22e&#34;&gt;getResponse&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;h3 id=&#34;2负载均衡&#34;&gt;（2）负载均衡&#xA;&lt;/h3&gt;&lt;h3 id=&#34;-feign-默认集成了-ribbon无需额外配置&#34;&gt;* Feign 默认集成了 Ribbon，无需额外配置&#xA;&lt;/h3&gt;&lt;h3 id=&#34;-可以通过配置文件自定义-ribbon-的负载均衡策略&#34;&gt;* 可以通过配置文件自定义 Ribbon 的负载均衡策略：&#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;service-name&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;ribbon&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;NFLoadBalancerRuleClassName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;com.netflix.loadbalancer.RoundRobinRule&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3熔断和降级&#34;&gt;（3）熔断和降级&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;通过 &lt;strong&gt;@FeignClient&lt;/strong&gt; 的** Fallback** 属性指定降级类：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;@FeignClient&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;service-name&amp;#34;&lt;/span&gt;, fallback &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; MyFeignClientFallback.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&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;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyFeignClient&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;@GetMapping&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/endpoint&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String &lt;span style=&#34;color:#a6e22e&#34;&gt;getResponse&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:#a6e22e&#34;&gt;@Component&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;MyFeignClientFallback&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; MyFeignClient {&#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;@Override&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; String &lt;span style=&#34;color:#a6e22e&#34;&gt;getResponse&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:#e6db74&#34;&gt;&amp;#34;Fallback response&amp;#34;&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;h3 id=&#34;4自定义配置&#34;&gt;（4）自定义配置&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;通过 **@Configuration **类自定义 Feign 的编码器、解码器和拦截器：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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:#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;FeignConfig&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; Encoder &lt;span style=&#34;color:#a6e22e&#34;&gt;feignEncoder&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; JacksonEncoder();&#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; Decoder &lt;span style=&#34;color:#a6e22e&#34;&gt;feignDecoder&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; JacksonDecoder();&#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; RequestInterceptor &lt;span style=&#34;color:#a6e22e&#34;&gt;feignRequestInterceptor&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; template &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; template.&lt;span style=&#34;color:#a6e22e&#34;&gt;header&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Bearer token&amp;#34;&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;feign-的使用场景&#34;&gt;Feign 的使用场景&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1微服务调用&#34;&gt;（1）微服务调用&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;在微服务架构中，Feign 常用于服务之间的调用&lt;/li&gt;&#xA;&lt;li&gt;自定义接口和注解，简化 HTTP 请求的编写&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2负载均衡-1&#34;&gt;（2）负载均衡&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 默认集成了 Ribbon，支持客户端负载均衡&lt;/li&gt;&#xA;&lt;li&gt;可以根据配置选择不同的负载均衡策略&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3熔断和降级-1&#34;&gt;（3）熔断和降级&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;通过集成 Hystrix，Feign 支持熔断和降级机制&lt;/li&gt;&#xA;&lt;li&gt;当服务不可用时，可以返回降级结果，避免系统崩溃&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4自定义-http-客户端&#34;&gt;（4）自定义 HTTP 客户端&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 支持自定义编码器、解码器和拦截器，满足复杂的业务需求&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;feign-的底层原理&#34;&gt;Feign 的底层原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1动态代理&#34;&gt;（1）动态代理&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 通过 JDK 动态代理或者 CGLIB 生成接口的实现类&lt;/li&gt;&#xA;&lt;li&gt;在运行时，Feign 会将方法调用转换为 HTTP 请求&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2请求模版&#34;&gt;（2）请求模版&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 使用 RequestTemplate 类表示 HTTP 请求模版&lt;/li&gt;&#xA;&lt;li&gt;通过解析接口注解和方法参数，生成具体的 HTTP 请求&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3编码器和解码器&#34;&gt;（3）编码器和解码器&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 使用编码器将 Java 对象转换为 HTTP 请求体&lt;/li&gt;&#xA;&lt;li&gt;使用编码器将 HTTP 响应体转为 Java 对象&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4拦截器&#34;&gt;（4）拦截器&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Feign 支持请求拦截器，可以在发送请求前修改请求头或者请求体&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;graph TD&#xA;    A[客户端调用 Feign 接口方法] --&gt; B[ReflectiveFeign.newInstance 创建动态代理]&#xA;    B --&gt; C[InvocationHandler.invoke 拦截方法调用]&#xA;    C --&gt; D[SynchronousMethodHandler.invoke 处理请求]&#xA;    D --&gt; E[RequestTemplate.Factory.create 生成请求模板]&#xA;    E --&gt; F[RequestInterceptor.apply 应用拦截器]&#xA;    F --&gt; G[Encoder.encode 编码请求体]&#xA;    G --&gt; H[LoadBalancerFeignClient.execute 选择服务实例]&#xA;    H --&gt; I[Client.execute 发送 HTTP 请求]&#xA;    I --&gt; J[Decoder.decode 解析响应]&#xA;    J --&gt; K[返回结果给客户端]&lt;/pre&gt;</description>
        </item><item>
            <title>Eureka</title>
            <link>https://xumf.net/blog/eureka/</link>
            <pubDate>Tue, 01 May 2018 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/eureka/</guid>
            <description>&lt;h1 id=&#34;eureka&#34;&gt;Eureka&#xA;&lt;/h1&gt;&lt;p&gt;配置中心核心功能：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;集中化管理&lt;/li&gt;&#xA;&lt;li&gt;版本管理&lt;/li&gt;&#xA;&lt;li&gt;动态更新&lt;/li&gt;&#xA;&lt;li&gt;权限控制&lt;/li&gt;&#xA;&lt;li&gt;环境隔离&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;基本功能：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;服务发现&#xA;eureka客户端可以向eureka服务端获取服务实例列表&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;服务注册&#xA;eureka客户端启动的时候&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;三级缓存&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;读缓存 ReadOnlyCache&lt;/li&gt;&#xA;&lt;li&gt;写缓存 WriteCache&lt;/li&gt;&#xA;&lt;li&gt;注册表缓存&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;自我保护机制&#xA;在网络通讯产生问题时，避免大量正常客服端实例被清除&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;eureka 自我保护机制服务端相关影响配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;eureka&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;server&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;enable-self-preservation&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#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:#f92672&#34;&gt;renewal-percent-threshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.85&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 续约百分比阈值，默认0.85&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;renewal-threshold-update-interval-ms&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;900000&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 更新阈值的时间间隔，默认15分钟&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;eureka 自我保护机制客户端相关影响配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;eureka&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;instance&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;lease-renewal-interval-in-seconds&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 客户端续约间隔，默认30秒&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;lease-expiration-duration-in-seconds&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;90&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# 服务过期时间，默认90秒&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;客户端服务注册流程&#34;&gt;客户端服务注册流程&#xA;&lt;/h4&gt;&lt;p&gt;每当有客服端服务启动时，客户端会根据配置eureka服务端的地址，向服务端发起注册动作，服务端收到注册请求，会更新注册表缓冲信息，增加新的客户端信息到注册表缓冲，然后将注册表信息更新到写缓存。&lt;/p&gt;&#xA;&lt;h4 id=&#34;客户端读取数据流程&#34;&gt;客户端读取数据流程&#xA;&lt;/h4&gt;&lt;ol&gt;&#xA;&lt;li&gt;客户端查看本地缓存是否存在&#xA;&lt;ol&gt;&#xA;&lt;li&gt;存在：直接返回本地缓存中的数据&lt;/li&gt;&#xA;&lt;li&gt;不存在：请求服务端获取数据&#xA;&lt;ol&gt;&#xA;&lt;li&gt;获取读缓存，存在直接返回；不存在直接进入下一步&lt;/li&gt;&#xA;&lt;li&gt;获取写缓存，存在直接返回，并且将数据更新到读缓存；不存在直接进入下一步&lt;/li&gt;&#xA;&lt;li&gt;获取注册表缓存，存在直接返回，并且将数据更新到读缓存与写缓存&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;缓存更新场景&#34;&gt;缓存更新场景&#xA;&lt;/h4&gt;&lt;p&gt;注册表更新场景：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;服务实例注册&lt;/li&gt;&#xA;&lt;li&gt;服务实例注销&lt;/li&gt;&#xA;&lt;li&gt;服务实例续约（心跳）&lt;/li&gt;&#xA;&lt;li&gt;服务实例状态变更&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;写缓存更新场景：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;每当注册表发生变化时，写缓存会被同时更新到最新的注册表信息&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;读缓存更新场景：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;每隔30s会同步写缓存数据&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h4 id=&#34;eureka-中服务实例的状态主要包括以下几种&#34;&gt;Eureka 中服务实例的状态主要包括以下几种：&#xA;&lt;/h4&gt;&lt;ul&gt;&#xA;&lt;li&gt;UP：服务实例正常运行，可接收请求。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当eureka服务实例发起服务注册时&lt;/li&gt;&#xA;&lt;li&gt;当eureka服务实例发起心跳，进行续期成功后，保持UP状态&lt;/li&gt;&#xA;&lt;li&gt;当eureka服务实例启动成功后，将状态从STARTING更改为UP&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;DOWN：服务实例不可用。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当eureka服务实例主动注销&lt;/li&gt;&#xA;&lt;li&gt;当eureka实例在规定的时间（默认90s）内没有发送心跳消息&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;STARTING：服务实例正在启动。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当服务器启动时&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;OUT_OF_SERVICE：服务实例被手动下线，不可用。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通过Eureka的管理接口或者UI，可以手动将状态从UP更改为OUT_OF_SERVICE&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;UNKNOWN：服务实例状态未知。&#xA;&lt;ul&gt;&#xA;&lt;li&gt;当网络分区时（网络问题导致服务之间无法通讯），Eureka服务端无法确认服务实例的状态时，就会将状态改为 UNKNOWN&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;eureka各端缓存应用交互&#34;&gt;Eureka各端缓存应用交互&#xA;&lt;/h4&gt;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;sequenceDiagram&#xA;    participant Client as 客户端&#xA;    participant LocalCache as 本地缓存&#xA;    participant EurekaServer as Eureka 服务器&#xA;    participant ServiceInstance as 服务实例&#xA;&#xA;    Client-&gt;&gt;LocalCache: 1. 检查本地缓存&#xA;    alt 缓存有效&#xA;        LocalCache--&gt;&gt;Client: 返回缓存的服务实例&#xA;    else 缓存无效或过期&#xA;        Client-&gt;&gt;EurekaServer: 2. 请求服务实例信息&#xA;        EurekaServer-&gt;&gt;EurekaServer: 3. 检查读缓存&#xA;        alt 读缓存有效&#xA;            EurekaServer--&gt;&gt;Client: 返回读缓存的服务实例&#xA;        else 读缓存过期&#xA;            EurekaServer-&gt;&gt;EurekaServer: 4. 从写缓存加载最新数据&#xA;            EurekaServer--&gt;&gt;Client: 返回最新的服务实例&#xA;        end&#xA;        Client-&gt;&gt;LocalCache: 5. 更新本地缓存&#xA;    end&#xA;    Client-&gt;&gt;ServiceInstance: 6. 调用目标服务实例&#xA;    Client-&gt;&gt;EurekaServer: 7. 定时拉取最新服务实例&#xA;    EurekaServer--&gt;&gt;Client: 返回最新的服务实例&#xA;    Client-&gt;&gt;LocalCache: 8. 更新本地缓存&lt;/pre&gt;</description>
        </item><item>
            <title>ZooKeeper</title>
            <link>https://xumf.net/blog/zookeeper/</link>
            <pubDate>Thu, 22 Mar 2018 22:21:04 +0800</pubDate>
            <guid>https://xumf.net/blog/zookeeper/</guid>
            <description>&lt;h2 id=&#34;zookeeper-核心原理&#34;&gt;ZooKeeper 核心原理&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;数据模型&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;ZNode：树形结构中的节点，存储数据（&amp;lt;=1MB）&lt;/li&gt;&#xA;&lt;li&gt;节点类型&#xA;&lt;ol&gt;&#xA;&lt;li&gt;持久节点：手动删除&lt;/li&gt;&#xA;&lt;li&gt;临时节点：会话结束自动删除&lt;/li&gt;&#xA;&lt;li&gt;顺序节点：名称追加单调递增序号&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;版本号：每个 ZNode 有版本号， 用于 CAS操作&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;架构与角色&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Leader：处理写请求，发起提案&lt;/li&gt;&#xA;&lt;li&gt;Follower：参与选举，处理读请求&lt;/li&gt;&#xA;&lt;li&gt;Observer：拓展读性能，不参与选举&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ZAB 协议&lt;/strong&gt;（ZooKeeper Atomic Broadcast）&#xA;&lt;ol&gt;&#xA;&lt;li&gt;恢复模式：选举 Leader （基于 zxid 和 myid，半数以上投票）&lt;/li&gt;&#xA;&lt;li&gt;广播模式：Leader 提出事物，半数以上 Follower 确认后提交&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;一致性保护&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;顺序一致性（客户端操作按顺序执行）&lt;/li&gt;&#xA;&lt;li&gt;原子性（事物要么全成功要么全失败）&lt;/li&gt;&#xA;&lt;li&gt;最终一致性（读请求可能返回旧值，但最终同步）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Watch 机制&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;客户端监听 ZNode 变化（如节点删除，数据更新）&lt;/li&gt;&#xA;&lt;li&gt;一次性触发，需要重新注册&lt;/li&gt;&#xA;&lt;li&gt;异步通知，可能存在延迟或丢失&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;典型应用场景&#34;&gt;典型应用场景&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;分布式锁&lt;/strong&gt;：通过临时顺序节点实现，避免惊群效应&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;配置管理&lt;/strong&gt;：集中存储配置，客户端监听变更&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务注册与发现&lt;/strong&gt;：临时节点表示服务实例在线状态&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;选主（Leader Election）&lt;/strong&gt;：最小序号节点成为 Master&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;分布式队列&lt;/strong&gt;：顺序节点实现生产消费模型&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;重要知识点&#34;&gt;重要知识点&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;ZooKeeper 如何保证数据一致性？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：通过 ZAB 协议，写操作需要半数以上节点确认，保证顺序一致性和原子性。读请求可能来自任意节点（可能读到旧数据），但可通过 &lt;code&gt;sync&lt;/code&gt; 操作强制读取最新值。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;临时节点的作用时什么？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：临时节点在会话结束后自动删除，常用于服务注册（服务下线自动清除）和分布式锁（客户端崩溃自动释放锁）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;如何处理脑裂问题？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：ZAB 协议要求写操作必须由 Leader 发起，且需要半数以上节点确认。网络分区时，仅拥有多数节点的分区能选举 Leader，另一个分区无法写入，避免数据不一致。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Watcher 机制有哪些主要事项？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：一次性触发、通知可能延迟、需要处理事件丢失（如 Watch 注册期间发生变更）。需在回调中重新注册 Watcher。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Leader 选举过程是怎样的？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：节点启动时进入选举状态，投票优先给 zxid 最大的节点，zxid 相同则选 myid 更大的。获得半数以上投票的节点成为 Leader。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;如何实现分布式锁？&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;答&lt;/strong&gt;：客户端创建临时顺序节点，检查是否为最小序号节点。若是则获得锁；否则监听前一个节点的删除事件，使用 &lt;code&gt;exists()&lt;/code&gt; +Watcher 避免轮询。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;性能与优化&#34;&gt;性能与优化&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;写性能&lt;/strong&gt;：依赖半数以上节点确认，建议集群节点数为奇数（如3、5）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;读性能&lt;/strong&gt;：可直接从本地节点读取，高吞吐。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;快照与日志&lt;/strong&gt;：定期生成快照（snapshot）和事务日志（txn log），加速恢复。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;配置与运维&#34;&gt;配置与运维&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;会话超时&lt;/strong&gt;：&lt;code&gt;tickTime&lt;/code&gt; 为基本时间单位，&lt;code&gt;sessionTimeout&lt;/code&gt; 建议2-20倍&lt;code&gt;tickTime&lt;/code&gt; 。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;数据持久化&lt;/strong&gt;：事务日志和快照存储于&lt;code&gt;dataDir&lt;/code&gt; 和&lt;code&gt;dataLogDir&lt;/code&gt; 。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ACL 控制&lt;/strong&gt;：支持IP、Digest等多种认证方式，精细化权限管理。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
        </item></channel>
</rss>
