<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>小蜜蜂</title>
        <link>https://xumf.net/</link>
        <description>Recent content 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/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 三级缓存</title>
            <link>https://xumf.net/blog/springthridlevelcache/</link>
            <pubDate>Thu, 30 Jan 2025 22:39:17 +0800</pubDate>
            <guid>https://xumf.net/blog/springthridlevelcache/</guid>
            <description>&lt;h2 id=&#34;三级缓存&#34;&gt;三级缓存&#xA;&lt;/h2&gt;&lt;p&gt;在 Spring 框架中，&lt;strong&gt;三级缓存&lt;/strong&gt;机制用于解决单例 Bean 的循环依赖问题。当两个或多个单例 Bean 相互依赖时，Spring 通过三级缓存来确保它们能够相互引用，避免了循环依赖倒置的错误。&lt;/p&gt;&#xA;&lt;h3 id=&#34;三级缓存的组成&#34;&gt;三级缓存的组成：&#xA;&lt;/h3&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;Spring的DefaultSingletonBeanRegistry类三级缓存对象&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&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;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Object&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; singletonObjects &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ConcurrentHashMap&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;(256);&#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; Map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Object&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; earlySingletonObjects &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ConcurrentHashMap&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;(16);&#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; Map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, ObjectFactory&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&amp;gt;&amp;gt;&lt;/span&gt; singletonFactories &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HashMap&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;gt;&lt;/span&gt;(16);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;一级缓存（&lt;strong&gt;&lt;strong&gt;singletonObjects&lt;/strong&gt;&lt;/strong&gt;）&lt;/strong&gt;：存放完全初始化的单例 Bean 实例。当请求一个 Bean 时，Spring 首先从一级缓存中查找，如果存在，则直接返回实例。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;二级缓存（&lt;strong&gt;&lt;strong&gt;earlySingletonObjects&lt;/strong&gt;&lt;/strong&gt;）&lt;/strong&gt;：存放尚未完全初始化的单例 Bean 实例，通常是指构造函数已执行完毕，但属性尚未填充的 Bean。当 Bean 的构造函数执行完毕后，但属性尚未填充的 Bean。当 Bean 的构造函数执行完毕后，Spring 会将其放入二级缓存中，以便在依赖注入过程中，其它 Bean 可以获取该 Bean 的早期引用，从而解决循环依赖。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;三级缓存（&lt;strong&gt;&lt;strong&gt;singletonFactories&lt;/strong&gt;&lt;/strong&gt;）&lt;/strong&gt;：存放用于创建单例 Bean 的工厂对象（ObjectFactory）。当 Bean 正在创建过程中，且需要提前暴露其引用时，Spring 会将用于创建该 Bean 的工厂对象放入三级缓存中。其它 Bean 在依赖注入时，可以通过三级缓存获取该工厂对象，从而获取正在创建中的 Bean 的引用。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;三级缓存解决下循环依赖的流程&#34;&gt;三级缓存解决下循环依赖的流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;实例化 Bean&lt;/strong&gt;：当 Spring 需要创建一个 Bean 时，首先会检查一级缓存中是否已有该 Bean 的实例。如果没有，则开始实例化该 Bean。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;放入三级缓存&lt;/strong&gt;：在实例化过程中，Spring 会将用于创建该 Bean 的工厂对象放入三级缓存中。这样，其它 Bean 在依赖注入时，可以通过三级缓存获取该工厂对象，从而获取到正在创建中的 Bean 的引用。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;放入二级缓存&lt;/strong&gt;：当 Bean 的构造函数执行完毕后，Spring 会将其放入二级缓存中。此时，其它 Bean 可以从二级缓存中获取到该 Bean 的早期引用。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;放入一级缓存&lt;/strong&gt;：当 Bean 的属性填充和初始化方法执行完毕后，Spring 会将其放入一级缓存，表示该 Bean 已完全初始化。此时，其它 Bean 可以从一级缓存中获取到该 Bean 的实例。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;为什么需要三级缓存&#34;&gt;为什么需要三级缓存？&#xA;&lt;/h3&gt;&lt;p&gt;虽然二级缓存可以解决大部分循环依赖问题，但在涉及 AOP（面向切面编程）时，三级缓存显得尤为重要。在 AOP 代理的情况下，Bean 的创建过程需要通过代理工厂来生成代理对象。三级缓存缓存中的工厂对象正是用于创建这些代理对象的。如果没有三级缓存，Spring 将无法在 Bean 创建过程中提前暴露代理对象，从而导致循环依赖无法解决。&lt;/p&gt;&#xA;&lt;p&gt;通过引用三级缓存，Spring 能够在 Bean 创建过程中提前暴露代理对象，确保循环依赖能够正确解决。这使得 Spring 在处理复杂的依赖关系时，能够保持高效和灵活。&lt;/p&gt;&#xA;&lt;p&gt;总之，Spring 的三级缓存机制通过合理的缓存策略，确保了单例 Bean 在存在循环依赖和 AOP 代理的情况下，能够正确地相互引用，避免了循环依赖导致的错误。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>Synchronized</title>
            <link>https://xumf.net/blog/synchronized/</link>
            <pubDate>Wed, 22 Jan 2025 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/synchronized/</guid>
            <description>&lt;p&gt;&lt;img alt=&#34;同步锁&#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;https://xumf.net/images/Synchronized.png&#34;&gt;&lt;/p&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>SpringBoot 启动流程</title>
            <link>https://xumf.net/blog/springbootstartflow/</link>
            <pubDate>Tue, 09 May 2023 23:36:22 +0800</pubDate>
            <guid>https://xumf.net/blog/springbootstartflow/</guid>
            <description>&lt;p&gt;Spring Boot 的启动入口是 &lt;code&gt;SpringApplication.run()&lt;/code&gt;，其核心流程可概括为三个阶段：&lt;strong&gt;准备阶段 → 刷新上下文 → 启动完成后的回调&lt;/strong&gt;。&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;1. SpringApplication.run() 入口&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2. 准备阶段：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 推断应用类型（Reactive / Servlet）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 加载所有 SpringApplicationRunListener&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 构建并准备 Environment（解析 application.yml/properties）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 打印 Banner&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3. 创建并准备 ApplicationContext：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 创建上下文实例（AnnotationConfigServletWebServerApplicationContext）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 执行 ApplicationContextInitializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 注册启动参数中的主配置类（@SpringBootApplication 标注的类）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 调用 refresh() 方法 → 进入 Spring 容器核心流程&#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;   ├─ 执行 CommandLineRunner / ApplicationRunner&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 启动内嵌 Web 容器（Tomcat / Jetty / Undertow）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;refresh()&lt;/code&gt; 方法是 Spring 容器初始化的核心，由 &lt;code&gt;AbstractApplicationContext.refresh()&lt;/code&gt; 定义，其中 13 个步骤依次执行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二refresh-核心步骤&#34;&gt;二、refresh() 核心步骤&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;refresh()&lt;/code&gt; 中的关键步骤（按顺序）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;prepareRefresh()&lt;/strong&gt;：设置容器状态，初始化属性源和早期事件发布器&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;obtainFreshBeanFactory()&lt;/strong&gt;：刷新 BeanFactory，解析 Bean 定义（从配置类、XML、@ComponentScan 扫描结果）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;prepareBeanFactory()&lt;/strong&gt;：配置 BeanFactory 的类加载器、SpEL 解析器、属性编辑器，注册 Aware 接口回调需要的 Bean&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;postProcessBeanFactory()&lt;/strong&gt;：子类扩展点（Web 容器在此注册 ServletContextAware 处理器）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;invokeBeanFactoryPostProcessors()&lt;/strong&gt;：调用所有 BeanFactoryPostProcessor。最关键的是 &lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt;，它解析 @Configuration、@ComponentScan、@Import、@Bean 并注册所有 Bean 定义&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;registerBeanPostProcessors()&lt;/strong&gt;：注册 BeanPostProcessor。此时只注册不执行——真正执行时机在 bean 实例化阶段触发&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;initMessageSource()&lt;/strong&gt;：初始化国际化组件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;initApplicationEventMulticaster()&lt;/strong&gt;：初始化事件广播器&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;onRefresh()&lt;/strong&gt;：创建并启动内嵌 Web 容器（Tomcat 在此启动）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;registerListeners()&lt;/strong&gt;：注册所有的 ApplicationListener&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;finishBeanFactoryInitialization()&lt;/strong&gt;：实例化所有非懒加载的单例 Bean——这是&lt;strong&gt;启动最耗时&lt;/strong&gt;的阶段&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;finishRefresh()&lt;/strong&gt;：发布 ContextRefreshedEvent 事件&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三核心-beanpostprocessor-详解&#34;&gt;三、核心 BeanPostProcessor 详解&#xA;&lt;/h2&gt;&lt;p&gt;BeanPostProcessor 在 bean 实例化过程的两个时机触发：&lt;strong&gt;初始化前（BeforeInitialization）&lt;/strong&gt; 和 &lt;strong&gt;初始化后（AfterInitialization）&lt;/strong&gt;。下面列出 Spring Boot 自动装配中最常用的几个：&lt;/p&gt;&#xA;&lt;h3 id=&#34;依赖注入相关&#34;&gt;依赖注入相关&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;AutowiredAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Autowired、@Value、@Inject&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization：解析注入点并注入依赖&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor&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;CommonAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 JSR-250 注解：@Resource、@PostConstruct、@PreDestroy&lt;/li&gt;&#xA;&lt;li&gt;@Resource 按名称优先注入，与 @Autowired 的 Type 优先策略不同——混用时注意&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.context.annotation.CommonAnnotationBeanPostProcessor&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;生命周期回调相关&#34;&gt;生命周期回调相关&#xA;&lt;/h3&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;InitDestroyAnnotationBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @PostConstruct 和 @PreDestroy&lt;/li&gt;&#xA;&lt;li&gt;与 CommonAnnotationBeanPostProcessor 的职责有重叠——InitDestroyAnnotationBeanPostProcessor 更底层，CommonAnnotationBeanPostProcessor 扩展了对 @Resource 的支持&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;aware-接口注入&#34;&gt;Aware 接口注入&#xA;&lt;/h3&gt;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;ApplicationContextAwareProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 ApplicationContextAware、EnvironmentAware、ResourceLoaderAware 等&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization 阶段注入，早于 @Autowired&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;占位符解析&#34;&gt;占位符解析&#xA;&lt;/h3&gt;&lt;ol start=&#34;5&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;EmbeddedValueResolverAwareBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 EmbeddedValueResolverAware 接口，注入 StringValueResolver&lt;/li&gt;&#xA;&lt;li&gt;用于解析 &lt;code&gt;${property}&lt;/code&gt; 占位符和 &lt;code&gt;#{spEL}&lt;/code&gt; 表达式&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;aop-代理&#34;&gt;AOP 代理&#xA;&lt;/h3&gt;&lt;ol start=&#34;6&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;InfrastructureAdvisorAutoProxyCreator&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;为符合条件的 Bean 生成 AOP 代理&lt;/li&gt;&#xA;&lt;li&gt;postProcessAfterInitialization 阶段触发：先有 Bean 实例，再通过代理增加切面逻辑&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.aop.framework.autoproxy. InfrastructureAdvisorAutoProxyCreator&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;异常转换&#34;&gt;异常转换&#xA;&lt;/h3&gt;&lt;ol start=&#34;7&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;PersistenceExceptionTranslationPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;将持久化层异常（JPA、Hibernate）转换为 Spring DataAccessException&lt;/li&gt;&#xA;&lt;li&gt;通常提前注册 BeanPostProcessor 以处理所有持久化 Bean&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;事件与注解驱动&#34;&gt;事件与注解驱动&#xA;&lt;/h3&gt;&lt;ol start=&#34;8&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;EventListenerMethodProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @EventListener，注册事件监听方法&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.context.event.EventListenerMethodProcessor&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;ScheduledAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Scheduled，注册定时任务&lt;/li&gt;&#xA;&lt;li&gt;与 @Async 由不同处理器管理：@Async 由 AsyncAnnotationBeanPostProcessor 处理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;import-扩展&#34;&gt;Import 扩展&#xA;&lt;/h3&gt;&lt;ol start=&#34;10&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;ImportAwareBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Import 导入的类中实现 ImportAware 接口的 Bean&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization 阶段注入导入元数据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;四beanfactorypostprocessor&#34;&gt;四、BeanFactoryPostProcessor&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;最重要的 BeanFactoryPostProcessor&lt;/strong&gt;，负责解析 @Configuration 类&lt;/li&gt;&#xA;&lt;li&gt;处理 @ComponentScan（包扫描）、@Import（导入配置类）、@Bean（方法级别 Bean 定义）&lt;/li&gt;&#xA;&lt;li&gt;在 invokeBeanFactoryPostProcessors() 阶段执行——比任何 BeanPostProcessor 都早&lt;/li&gt;&#xA;&lt;li&gt;没有它，所有注解配置的 Bean 都不会被注册&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;排查点：finishBeanFactoryInitialization 阶段耗时最长，检查是否有大量懒加载泄漏、@ComponentScan 覆盖过多包路径&lt;/li&gt;&#xA;&lt;li&gt;启用 lazy-initialization（&lt;code&gt;spring.main.lazy-initialization=true&lt;/code&gt;）可加速启动，但注意首次请求变慢&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Bean 初始化异常如何排查？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;开启 &lt;code&gt;debug=true&lt;/code&gt; 查看 ConditionEvaluationReport（自动配置条件评估报告）&lt;/li&gt;&#xA;&lt;li&gt;关键日志关键词：&lt;code&gt;UnsatisfiedDependencyException&lt;/code&gt;、&lt;code&gt;BeanCreationException&lt;/code&gt;、&lt;code&gt;NoSuchBeanDefinitionException&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;AOP 代理不生效？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查类是否被 final 修饰（CGLIB 无法代理 final 类）&lt;/li&gt;&#xA;&lt;li&gt;检查同一个类内部方法调用 AOP 代理问题（自调用不走代理）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;@PostConstruct 与 afterPropertiesSet 的执行顺序？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;InitializingBean.afterPropertiesSet()&lt;/code&gt; → &lt;code&gt;@PostConstruct&lt;/code&gt; → 自定义 &lt;code&gt;init-method&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;顺序：InitializingBean → BeanPostProcessor.postProcessBeforeInitialization → @PostConstruct → afterPropertiesSet → init-method → BeanPostProcessor.postProcessAfterInitialization&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor 的常见错误&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;@ComponentScan 未生效：检查启动类的位置是否在根包&lt;/li&gt;&#xA;&lt;li&gt;@Bean 方法被 final 修饰：CGLIB 无法重写 final 方法&lt;/li&gt;&#xA;&lt;li&gt;@Import 导入的配置类重复：Spring 5.2+ 支持 @Import 去重，但注意 @Import 和 @ComponentScan 同时扫描到同一个类会导致重复注册&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>RabbitMQ 深入浅出</title>
            <link>https://xumf.net/blog/rabbitmq/</link>
            <pubDate>Fri, 03 Mar 2023 20:54:29 +0800</pubDate>
            <guid>https://xumf.net/blog/rabbitmq/</guid>
            <description>&lt;h1 id=&#34;rabbitmq-知识架构&#34;&gt;RabbitMQ 知识架构&#xA;&lt;/h1&gt;&lt;h2 id=&#34;1-amqp-协议基础&#34;&gt;1. AMQP 协议基础&#xA;&lt;/h2&gt;&lt;p&gt;RabbitMQ 是 AMQP 0-9-1 协议的实现，其核心模型基于&lt;strong&gt;信道（Channel）&lt;/strong&gt;、**交换机（Exchange）&lt;strong&gt;和&lt;/strong&gt;队列（Queue）**的协作。&lt;/p&gt;&#xA;&lt;h3 id=&#34;为什么需要-channel&#34;&gt;为什么需要 Channel？&#xA;&lt;/h3&gt;&lt;p&gt;AMQP 的设计用意：每次请求都创建 TCP 连接代价太高（三次握手+慢启动），Channel 是 TCP 内的虚拟链路，多个 Channel 复用同一个 TCP 连接。每个 Channel 独立处理消息路由，支持多线程并发。&lt;/p&gt;&#xA;&lt;p&gt;相关概念：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;虚拟主机（VHost）&lt;/strong&gt;：逻辑隔离环境，每个 VHost 拥有独立的交换机、队列和权限。一个 RabbitMQ 实例可以创建多个 VHost，用于多租户隔离。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;帧（Frame）&lt;/strong&gt;：AMQP 数据传输的最小单位，包含帧头、帧体和帧尾，用于封装消息和协议指令。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;2-消息流转原理&#34;&gt;2. 消息流转原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;生产者发送消息&#34;&gt;生产者发送消息&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;生产者 → TCP 连接 → Channel → basic.publish(exchange, routingKey, props, body) → Exchange&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;关键参数：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;exchange&lt;/code&gt;：目标交换机&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;routing_key&lt;/code&gt;：路由键（交换机据此路由）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;mandatory&lt;/code&gt;：true 时消息无法路由则返回错误，false 时消息丢失&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;delivery_mode&lt;/code&gt;：2 表示持久化消息&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;交换机类型&#34;&gt;交换机类型&#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;&#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;strong&gt;Direct&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;精确匹配 &lt;code&gt;routing_key&lt;/code&gt; = &lt;code&gt;binding_key&lt;/code&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;strong&gt;Fanout&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;广播到所有绑定队列，忽略 routing_key&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;strong&gt;Topic&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;通配符匹配 &lt;code&gt;*&lt;/code&gt;（一个单词）&lt;code&gt;#&lt;/code&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;strong&gt;Headers&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;根据消息 header 键值对匹配&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;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;strong&gt;自动 ACK&lt;/strong&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;strong&gt;手动 ACK（basic.ack）&lt;/strong&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;无（除非消费者忘记 ACK）&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;手动 ACK 的注意事项：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;不 ACK 也不拒绝，消息会一直留在队列中（unacked）&lt;/li&gt;&#xA;&lt;li&gt;消费者断开连接后，unacked 消息重新入队（requeue），支持重试&lt;/li&gt;&#xA;&lt;li&gt;拒绝时 &lt;code&gt;requeue=true&lt;/code&gt; 会重新入队（可能导致死循环），&lt;code&gt;requeue=false&lt;/code&gt; 进入死信队列&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;3-持久化与可靠性&#34;&gt;3. 持久化与可靠性&#xA;&lt;/h2&gt;&lt;h3 id=&#34;消息持久化三要素&#34;&gt;消息持久化三要素&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;队列 durable = true  +  消息 delivery_mode = 2  +  Publisher Confirm&#xA;&lt;/code&gt;&lt;/pre&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;没有 Confirm → 不知道消息是否到达 Broker&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;publisher-confirm-模式&#34;&gt;Publisher Confirm 模式&#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;// Spring AMQP 示例: 启用 Confirm&lt;/span&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; RabbitTemplate &lt;span style=&#34;color:#a6e22e&#34;&gt;rabbitTemplate&lt;/span&gt;(ConnectionFactory connectionFactory) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    RabbitTemplate template &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RabbitTemplate(connectionFactory);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    template.&lt;span style=&#34;color:#a6e22e&#34;&gt;setConfirmCallback&lt;/span&gt;((correlationData, ack, cause) &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;if&lt;/span&gt; (ack) {&#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;// 消息成功到达 Exchange&lt;/span&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;else&lt;/span&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;// 消息到达 Exchange 失败，记录日志/重试&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;    template.&lt;span style=&#34;color:#a6e22e&#34;&gt;setMandatory&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;    template.&lt;span style=&#34;color:#a6e22e&#34;&gt;setReturnsCallback&lt;/span&gt;(returned &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;// 消息无法路由到 Queue（mandatory=true 时触发）&lt;/span&gt;&#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;warn&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;消息不可路由: {}&amp;#34;&lt;/span&gt;, returned.&lt;span style=&#34;color:#a6e22e&#34;&gt;getMessage&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; template;&#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;Confirm 和 Return 的区别：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Confirm&lt;/strong&gt;：确认消息是否到达 Exchange&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Return&lt;/strong&gt;：确认消息从 Exchange 是否路由到 Queue（mandatory=true）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;4-死信队列dlx&#34;&gt;4. 死信队列（DLX）&#xA;&lt;/h2&gt;&lt;h3 id=&#34;触发条件&#34;&gt;触发条件&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;消息被消费者拒绝（&lt;code&gt;basic.reject&lt;/code&gt; / &lt;code&gt;basic.nack&lt;/code&gt;）+ &lt;code&gt;requeue=false&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;消息 TTL 过期（&lt;code&gt;expiration&lt;/code&gt; 属性）&lt;/li&gt;&#xA;&lt;li&gt;队列达到最大长度（&lt;code&gt;x-max-length&lt;/code&gt; / &lt;code&gt;x-max-length-bytes&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;消息超过队列的 TTL（&lt;code&gt;x-message-ttl&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;应用场景&#34;&gt;应用场景&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;延迟队列&lt;/strong&gt;：消息设置 TTL → 过期后进入死信队列 → 消费者从死信队列消费。不需要额外插件。&lt;/li&gt;&#xA;&lt;/ul&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:#75715e&#34;&gt;// Spring Boot 配置延迟队列（通过死信实现）&lt;/span&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; Queue &lt;span style=&#34;color:#a6e22e&#34;&gt;normalQueue&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Object&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; args &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HashMap&lt;span style=&#34;color:#f92672&#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;    args.&lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x-dead-letter-exchange&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dlx.exchange&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args.&lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x-dead-letter-routing-key&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dlx.routing.key&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args.&lt;span style=&#34;color:#a6e22e&#34;&gt;put&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;x-message-ttl&amp;#34;&lt;/span&gt;, 30000); &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:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Queue(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;normal.queue&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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;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; Queue &lt;span style=&#34;color:#a6e22e&#34;&gt;dlq&lt;/span&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; Queue(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dlq.queue&amp;#34;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;&lt;h2 id=&#34;5-集群与高可用&#34;&gt;5. 集群与高可用&#xA;&lt;/h2&gt;&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;strong&gt;问题&lt;/strong&gt;：队列所在节点宕机 → 队列数据丢失&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;镜像队列quorum-queue-替代&#34;&gt;镜像队列（Quorum Queue 替代）&#xA;&lt;/h3&gt;&lt;p&gt;从 RabbitMQ 3.8 起，推荐使用 &lt;strong&gt;Quorum Queue&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;镜像队列&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;Quorum Queue&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;GM（Guaranteed Multicast）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Raft&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;Master-Slave&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Leader-Follower&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;自动（Raft 自动选主）&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;p&gt;&lt;strong&gt;生产环境推荐&lt;/strong&gt;：新项目直接使用 Quorum Queue。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;6-性能优化&#34;&gt;6. 性能优化&#xA;&lt;/h2&gt;&lt;h3 id=&#34;qos-预取&#34;&gt;QoS 预取&#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;// Spring Boot: 每次只拉取 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:#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; SimpleRabbitListenerContainerFactory &lt;span style=&#34;color:#a6e22e&#34;&gt;myFactory&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ConnectionFactory connectionFactory) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SimpleRabbitListenerContainerFactory factory &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; SimpleRabbitListenerContainerFactory();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    factory.&lt;span style=&#34;color:#a6e22e&#34;&gt;setConnectionFactory&lt;/span&gt;(connectionFactory);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    factory.&lt;span style=&#34;color:#a6e22e&#34;&gt;setPrefetchCount&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;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; factory;&#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;prefetchCount 的选择&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;= 1：公平分发，适合处理时间不均匀的任务，但吞吐量低&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;1：批量拉取，吞吐量高，但可能出现&amp;quot;慢消费者囤积任务&amp;quot;&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;批量操作&#34;&gt;批量操作&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;批量发布：合并多个消息到单次网络帧&#xA;批量 Confirm：multiple=true 一次性确认多条消息&#xA;批量 ACK：消费者处理一批后统一 ACK&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;&#xA;&lt;h2 id=&#34;7-常见问题排查&#34;&gt;7. 常见问题排查&#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;durable=true&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;检查消息 &lt;code&gt;delivery_mode=2&lt;/code&gt;（Spring Boot 通过 &lt;code&gt;spring.rabbitmq.template.mandatory=true&lt;/code&gt; + &lt;code&gt;MessageDeliveryMode.PERSISTENT&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;检查是否开启了 Confirm 模式&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;concurrency&lt;/code&gt; 参数）&lt;/li&gt;&#xA;&lt;li&gt;消费者处理异常一直失败 → 检查 &lt;code&gt;maxLength&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;消费者 ACK 超时后消息重新入队&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;根本解决方案&lt;/strong&gt;：生产者幂等（每条消息 &lt;code&gt;correlationId&lt;/code&gt; 唯一）+ 消费者侧去重（数据库唯一键 / Redis 原子操作）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Linux 文件句柄限制&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;RabbitMQ 打开大量文件（队列、连接），超过系统限制会崩溃&lt;/li&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;ulimit -n&lt;/code&gt;，调整 &lt;code&gt;/etc/security/limits.conf&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;使用 &lt;code&gt;rabbitmqctl status&lt;/code&gt; 查看内存、磁盘、连接数&lt;/li&gt;&#xA;&lt;li&gt;管理界面监控 &lt;code&gt;Queued Messages&lt;/code&gt; / &lt;code&gt;Message Rates&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;Spring Boot 连接 RabbitMQ 失败&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;spring.rabbitmq.host&lt;/code&gt;、&lt;code&gt;port&lt;/code&gt;（5672 不是 15672）&lt;/li&gt;&#xA;&lt;li&gt;检查 Virtual Host 是否存在（&lt;code&gt;spring.rabbitmq.virtual-host&lt;/code&gt; 默认 &lt;code&gt;/&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;检查防火墙和认证凭据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Netty知识</title>
            <link>https://xumf.net/blog/netty/</link>
            <pubDate>Wed, 22 Jun 2022 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/netty/</guid>
            <description>&lt;h2 id=&#34;一netty-线程模型与-reactor-模式&#34;&gt;一、Netty 线程模型与 Reactor 模式&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;主从 Reactor 多线程模型&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Netty 采用主从 Reactor 模型，核心组件为&lt;code&gt;EventLoopGroup&lt;/code&gt; ：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;BossGroup(主 Reactor)&lt;/strong&gt;：负责监听客户端连接，通过&lt;code&gt;Selector&lt;/code&gt; 将新连接注册到 WorkerGroup 中的某个&lt;code&gt;EventLoop&lt;/code&gt; 。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;WorkerGroup(从 Reactor)&lt;/strong&gt;：处理已建立连接的 I/O 事件（入读写）及业务逻辑，每个&lt;code&gt;EventLoop&lt;/code&gt; 绑定一个线程，通过轮询&lt;code&gt;Selector&lt;/code&gt; 监听多个&lt;code&gt;Channel&lt;/code&gt; 事件，避免线程切换开销。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;主从 Reactor 配置示例&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;EventLoopGroup bossGroup &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; NioEventLoopGroup(1); &lt;span style=&#34;color:#75715e&#34;&gt;// 主Reactor，一般只需1个线程处理连接&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EventLoopGroup workerGroup &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; NioEventLoopGroup(); &lt;span style=&#34;color:#75715e&#34;&gt;// 从Reactor，默认线程数=CPU核心*2&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;ServerBootstrap b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ServerBootstrap();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b.&lt;span style=&#34;color:#a6e22e&#34;&gt;group&lt;/span&gt;(bossGroup, workerGroup)&#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;channel&lt;/span&gt;(NioServerSocketChannel.&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:#a6e22e&#34;&gt;childHandler&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ChannelInitializer&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;SocketChannel&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:#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;protected&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;initChannel&lt;/span&gt;(SocketChannel ch) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         ch.&lt;span style=&#34;color:#a6e22e&#34;&gt;pipeline&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;addLast&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyBusinessHandler());&#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;调优点：&#xA;* &lt;code&gt;bossGroup&lt;/code&gt; 线程数通常为1（除非需要多端口监听）&#xA;* &lt;code&gt;workerGroup&lt;/code&gt; 线程数根据业务类型调整：&#xA;* CPU 密集型：线程数 ≈ CPU 核心数&#xA;* I/O 密集型：线程数 ≈ CPU 核心数 * 2&#xA;* 使用 Epoll 模式（Linux 环境）：&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;EventLoopGroup group &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; EpollEventLoopGroup();&#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;p&gt;Netty 通过 &lt;code&gt;ChannelPipeline&lt;/code&gt; 将事件处理任务分配给固定的&lt;code&gt;EventLoop&lt;/code&gt; 线程执行，保证同一连接的所有操作在同一个线程内完成，避免多线程竞争，减少锁的使用。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;二零拷贝zero-copy的深度实现&#34;&gt;二、零拷贝(Zero-Copy)的深度实现&#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;使用&lt;code&gt;FileRegion&lt;/code&gt; 和&lt;code&gt;transferTo()&lt;/code&gt; 方法，文件数据直接从内核缓冲区通过 DMA 传输到 Socket 缓冲区，无需用户态与内核态的数据拷贝。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;Netty 层的优化&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;CompositeByteBuf&lt;/strong&gt;：合并多个&lt;code&gt;ByteBuf&lt;/code&gt; 为逻辑视图，避免物理内存拷贝。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;直接内存(Direct Buffer)&lt;/strong&gt;：分配堆外内存，避免 JVM 堆与 Socket 缓冲区间的拷贝，但需要手动管理内存释放。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;示例：&lt;/strong&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;FileRegion 实现文件传输(零拷贝)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;File file &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; File(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;largefile.zip&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FileInputStream fis &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; FileInputStream(file);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FileRegion region &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DefaultFileRegion(fis.&lt;span style=&#34;color:#a6e22e&#34;&gt;getChannel&lt;/span&gt;(), 0, file.&lt;span style=&#34;color:#a6e22e&#34;&gt;length&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;ctx.&lt;span style=&#34;color:#a6e22e&#34;&gt;channel&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;writeAndFlush&lt;/span&gt;(region).&lt;span style=&#34;color:#a6e22e&#34;&gt;addListener&lt;/span&gt;(future &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;    fis.&lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&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; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;future.&lt;span style=&#34;color:#a6e22e&#34;&gt;isSuccess&lt;/span&gt;()) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        future.&lt;span style=&#34;color:#a6e22e&#34;&gt;cause&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;printStackTrace&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;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;CompositeByteBuf 合并缓冲区&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ByteBuf header &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Unpooled.&lt;span style=&#34;color:#a6e22e&#34;&gt;copiedBuffer&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Header&amp;#34;&lt;/span&gt;, CharsetUtil.&lt;span style=&#34;color:#a6e22e&#34;&gt;UTF_8&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ByteBuf body &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Unpooled.&lt;span style=&#34;color:#a6e22e&#34;&gt;copiedBuffer&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Body&amp;#34;&lt;/span&gt;, CharsetUtil.&lt;span style=&#34;color:#a6e22e&#34;&gt;UTF_8&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;CompositeByteBuf compositeBuf &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Unpooled.&lt;span style=&#34;color:#a6e22e&#34;&gt;compositeBuffer&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;compositeBuf.&lt;span style=&#34;color:#a6e22e&#34;&gt;addComponents&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;, header, body); &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;&lt;strong&gt;调优点&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;堆外内存（Direct Buffer）分配：&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;ByteBuf directBuf &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ByteBufAllocator.&lt;span style=&#34;color:#a6e22e&#34;&gt;DEFAULT&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;directBuffer&lt;/span&gt;(1024);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;监控 Direct Buffer 使用量（避免 OOM）：&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-Dio.netty.maxDirectMemory&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256M  &lt;span style=&#34;color:#75715e&#34;&gt;# JVM参数限制最大堆外内存&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;&lt;h2 id=&#34;三内存管理与性能优化&#34;&gt;三、内存管理与性能优化&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存池(PooledByteBufAllocator)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Netty 通过对象池复用&lt;code&gt;ByteBuf&lt;/code&gt; ，减少频繁的内存分配与 GC 压力。直接内存池采用 Buddy 算法管理内存块，提升分配效率。&lt;/p&gt;&#xA;&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;p&gt;通过&lt;code&gt;ReferenceCounted&lt;/code&gt; 接口实现引用计数，结合&lt;code&gt;ResourceLeakDetector&lt;/code&gt; 监控未释放的&lt;code&gt;ByteBuf&lt;/code&gt; ，防止内存泄漏。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存泄漏检测配置&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:#75715e&#34;&gt;// 设置泄漏检测级别（生产环境建议SIMPLE）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ResourceLeakDetector.&lt;span style=&#34;color:#a6e22e&#34;&gt;setLevel&lt;/span&gt;(ResourceLeakDetector.&lt;span style=&#34;color:#a6e22e&#34;&gt;Level&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;PARANOID&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;ByteBuf buf &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ByteBufAllocator.&lt;span style=&#34;color:#a6e22e&#34;&gt;DEFAULT&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;buffer&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;buf.&lt;span style=&#34;color:#a6e22e&#34;&gt;retain&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;buf.&lt;span style=&#34;color:#a6e22e&#34;&gt;release&lt;/span&gt;(); &lt;span style=&#34;color:#75715e&#34;&gt;// 减少引用计数，当计数=0时释放内存&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;内存池配置&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:#75715e&#34;&gt;// 服务端启用内存池&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ServerBootstrap bootstrap &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ServerBootstrap();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bootstrap.&lt;span style=&#34;color:#a6e22e&#34;&gt;childOption&lt;/span&gt;(ChannelOption.&lt;span style=&#34;color:#a6e22e&#34;&gt;ALLOCATOR&lt;/span&gt;, PooledByteBufAllocator.&lt;span style=&#34;color:#a6e22e&#34;&gt;DEFAULT&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;调优参数&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-Dio.netty.allocator.type=pooled&lt;/code&gt; 强制启用内存池&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-Dio.netty.allocator.maxOrder=5&lt;/code&gt; 调整内存块大小（默认11，对应8MB块）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-Dio.netty.threadLocalDirectBufferSize=0&lt;/code&gt; 禁用 ThreadLoad 缓存（大内存场景）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;四tcp-粘包拆包解决方案&#34;&gt;四、TCP 粘包/拆包解决方案&#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;：&lt;code&gt;FixedLengthFrameDecoder&lt;/code&gt; 处理固定长度消息。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;分隔符协议&lt;/strong&gt;：&lt;code&gt;DelimiterBasedFrameDecoder&lt;/code&gt; 按自定义分隔符（如&lt;code&gt;\n&lt;/code&gt; ）拆分数据。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;头部长度字段协议&lt;/strong&gt;：&lt;code&gt;LengthFieldBasedFrameDecoder&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;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;结合&lt;code&gt;MessageToByteEncoder&lt;/code&gt; 和&lt;code&gt;ByteToMessageDecoder&lt;/code&gt; 实现私有协议，例如 Dubbo 的协议头设计。&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:#75715e&#34;&gt;// 协议格式：4字节长度 + 数据&lt;/span&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;CustomDecoder&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; LengthFieldBasedFrameDecoder {&#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;CustomDecoder&lt;/span&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;super&lt;/span&gt;(1024 &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; 1024, 0, 4, 0, 4); &lt;span style=&#34;color:#75715e&#34;&gt;// 最大长度1MB，长度字段偏移0&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;protected&lt;/span&gt; Object &lt;span style=&#34;color:#a6e22e&#34;&gt;decode&lt;/span&gt;(ChannelHandlerContext ctx, ByteBuf in) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; Exception {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ByteBuf frame &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (ByteBuf) &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;decode&lt;/span&gt;(ctx, in);&#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; (frame &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&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;int&lt;/span&gt; dataLength &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; frame.&lt;span style=&#34;color:#a6e22e&#34;&gt;readInt&lt;/span&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;byte&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;byte&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;dataLength&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;        frame.&lt;span style=&#34;color:#a6e22e&#34;&gt;readBytes&lt;/span&gt;(data);&#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; String(data, StandardCharsets.&lt;span style=&#34;color:#a6e22e&#34;&gt;UTF_8&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;// 添加解码器到Pipeline&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipeline.&lt;span style=&#34;color:#a6e22e&#34;&gt;addLast&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; CustomDecoder());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipeline.&lt;span style=&#34;color:#a6e22e&#34;&gt;addLast&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyBusinessHandler());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#xA;&lt;h2 id=&#34;五心跳机制与长连接管理&#34;&gt;五、心跳机制与长连接管理&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;IdleStateHandler&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;监控读写空闲时间，触发&lt;code&gt;IdleStateEvent&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;pipeline.&lt;span style=&#34;color:#a6e22e&#34;&gt;addLast&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; IdleStateHandler(30, 0, 0, TimeUnit.&lt;span style=&#34;color:#a6e22e&#34;&gt;SECONDS&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipeline.&lt;span style=&#34;color:#a6e22e&#34;&gt;addLast&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HeartbeatHandler()); &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;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;TCP Keep-Alive 与应用层心跳&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;TCP 层 Keep-Alive 间隔较长（默认2小时），应用层心跳（如每30秒一次）更灵活，可快速检测网络异常。&lt;/p&gt;&#xA;&lt;hr&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;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;基于NIO的非阻塞 I/O，通过&lt;code&gt;ChannelFuture&lt;/code&gt; 实现异步回调，避免线程阻塞。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;责任链模式(ChannelPipeline)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;将编解码、业务逻辑等&lt;code&gt;ChannelHanlder&lt;/code&gt; 串联成链，事件按顺序传播，支持动态扩展。&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;线程局部变量(FastThreadLocal)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Netty 优化了 JDK 的&lt;code&gt;ThreadLocal&lt;/code&gt;，减少哈希冲突，提升访问速度。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;七高性能调优参数&#34;&gt;七、高性能调优参数&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Linux 系统参数调优&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-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;ulimit -n &lt;span style=&#34;color:#ae81ff&#34;&gt;1000000&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;# TCP缓冲区设置&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -w net.core.rmem_max&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16777216&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -w net.core.wmem_max&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16777216&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -w net.ipv4.tcp_rmem&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;4096 87380 16777216&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sysctl -w net.ipv4.tcp_wmem&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;4096 65536 16777216&amp;#34;&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;Netty 关键参数&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-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;bootstrap.&lt;span style=&#34;color:#a6e22e&#34;&gt;option&lt;/span&gt;(ChannelOption.&lt;span style=&#34;color:#a6e22e&#34;&gt;SO_BACKLOG&lt;/span&gt;, 1024) &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;option&lt;/span&gt;(ChannelOption.&lt;span style=&#34;color:#a6e22e&#34;&gt;SO_REUSEADDR&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;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         .&lt;span style=&#34;color:#a6e22e&#34;&gt;childOption&lt;/span&gt;(ChannelOption.&lt;span style=&#34;color:#a6e22e&#34;&gt;TCP_NODELAY&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// 禁用Nagle算法&lt;/span&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;childOption&lt;/span&gt;(ChannelOption.&lt;span style=&#34;color:#a6e22e&#34;&gt;SO_KEEPALIVE&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 启用TCP Keep-Alive&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;JVM 参数调优&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-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;-XX:MaxDirectMemorySize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m&#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;# GC优化（G1为例）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+UseG1GC &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:InitiatingHeapOccupancyPercent&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&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;调整 Epoll 事件触发模式&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;EpollEventLoopGroup group &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; EpollEventLoopGroup();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bootstrap.&lt;span style=&#34;color:#a6e22e&#34;&gt;channel&lt;/span&gt;(EpollServerSocketChannel.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 使用Epoll边缘触发&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;减少上下文切换&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;workerGroup.&lt;span style=&#34;color:#a6e22e&#34;&gt;setIoRatio&lt;/span&gt;(70); &lt;span style=&#34;color:#75715e&#34;&gt;// I/O任务占比70%，业务任务30%&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;连接数监控&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;ChannelGroup allChannels &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DefaultChannelGroup(GlobalEventExecutor.&lt;span style=&#34;color:#a6e22e&#34;&gt;INSTANCE&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;allChannels.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(channel); &lt;span style=&#34;color:#75715e&#34;&gt;// 维护所有活跃Channel&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-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;// 业务Handler中提交异步任务&lt;/span&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;channelRead&lt;/span&gt;(ChannelHandlerContext ctx, Object msg) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    executorService.&lt;span style=&#34;color:#a6e22e&#34;&gt;execute&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;        Object result &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; heavyCompute(msg); &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;        ctx.&lt;span style=&#34;color:#a6e22e&#34;&gt;writeAndFlush&lt;/span&gt;(result);&#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;&lt;strong&gt;如何避免 Epoll 空轮询 Bug？&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Netty 通过重建 Selector 解决 JDK NIO 的空轮询问题：当 Selector 空轮询次数超过阈值，重新注册 Channel 到新 Selector。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;Channel.write() 与 ChannelHandlerContext.write() 的却别？&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;code&gt;Channel.write()&lt;/code&gt; 从 Pipeline 尾部开始传播，&lt;code&gt;ChannelHandlerContext.write()&lt;/code&gt; 从当前 Handler 的下一个节点开始，影响事件处理路径。&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;如何实现百万级长连接？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;调整系统参数：最大文件描述符数、TCP 缓冲区大小。&lt;/li&gt;&#xA;&lt;li&gt;是用 Epoll 边缘触发模式（&lt;code&gt;EpollEventLoopGroup&lt;/code&gt; ）&lt;/li&gt;&#xA;&lt;li&gt;优化内存管理，避免频繁 GC。&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;-Dio.netty.leakDetection.level=paranoid&lt;/code&gt; 开启详细日志&lt;/li&gt;&#xA;&lt;li&gt;通过&lt;code&gt;jmap -histo:live &amp;lt;pid&amp;gt;&lt;/code&gt; 查看 Direct Buffer 数量&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CPU 100%排查&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;top -Hp &amp;lt;pid&amp;gt;&lt;/code&gt; 找到高 CPU 线程&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;jstack &amp;lt;pid&amp;gt;&lt;/code&gt; 查看线程堆栈，定位 EventLoop 阻塞点&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;netstat -ant|awk &#39;/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}&lt;/code&gt; 监控 TCP 状态&lt;/li&gt;&#xA;&lt;li&gt;通过 Wireshark 抓包分析粘包/拆包&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>JMM</title>
            <link>https://xumf.net/blog/javamemorymodel/</link>
            <pubDate>Fri, 09 Jul 2021 23:36:22 +0800</pubDate>
            <guid>https://xumf.net/blog/javamemorymodel/</guid>
            <description>&lt;p&gt;Java Memory Model（JMM）是 Java 虚拟机规范中定义的一组规则，用于屏蔽不同硬件和操作系统的内存访问差异，保证 Java 程序在多线程环境下的&lt;strong&gt;原子性、可见性、有序性&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;一为什么需要-jmm&#34;&gt;一、为什么需要 JMM？&#xA;&lt;/h2&gt;&lt;p&gt;多线程环境下，每个 CPU 核心都有自己的缓存（L1/L2/L3），主内存中的数据被多个核心同时读写时会出现三个问题：&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;JMM 定义了主内存和工作内存的交互规范，以及 &lt;code&gt;happens-before&lt;/code&gt; 规则来约束重排序。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二jmm-的内存操作&#34;&gt;二、JMM 的内存操作&#xA;&lt;/h2&gt;&lt;p&gt;JMM 定义了 8 种内存操作来完成变量在主内存和工作内存之间的同步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;lock&lt;/strong&gt;：作用于主内存，将变量锁定为当前线程独享&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;unlock&lt;/strong&gt;：作用于主内存，释放锁定&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;read&lt;/strong&gt;：作用于主内存，将变量值从主内存传输到工作内存&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;load&lt;/strong&gt;：作用于工作内存，将 read 操作传输来的值放入工作内存副本&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;use&lt;/strong&gt;：作用于工作内存，将工作内存中的变量值传递给执行引擎&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;assign&lt;/strong&gt;：作用于工作内存，将执行引擎计算的值赋给工作内存副本&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;store&lt;/strong&gt;：作用于工作内存，将工作内存中的变量值传送到主内存&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;write&lt;/strong&gt;：作用于主内存，将 store 操作传来的值写入主内存&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这 8 个操作必须满足以下规则：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;read 和 load、store 和 write 必须成对出现&lt;/li&gt;&#xA;&lt;li&gt;assign 不能单独发生（必须有 use 先获取值才能 assign）&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;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;sequenceDiagram&#xA;    participant 主内存&#xA;    participant 工作内存&#xA;    participant 线程&#xA;&#xA;    Note over 主内存,工作内存: 读取变量（主内存 → 工作内存）&#xA;    线程 -&gt;&gt; 主内存: read(var)&#xA;    主内存 --&gt;&gt; 工作内存: 传输变量值&#xA;    线程 -&gt;&gt; 工作内存: load(var)&#xA;&#xA;    Note over 工作内存: 修改变量（工作内存内操作）&#xA;    线程 -&gt;&gt; 工作内存: assign(var, newValue)&#xA;&#xA;    Note over 工作内存,主内存: 写回变量（工作内存 → 主内存）&#xA;    线程 -&gt;&gt; 工作内存: store(var)&#xA;    工作内存 --&gt;&gt; 主内存: 传输变量值&#xA;    线程 -&gt;&gt; 主内存: write(var)&lt;/pre&gt;&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;count++&lt;/code&gt; 实际上是 read→load→use→assign→store→write 六个步骤，线程 A 和线程 B 可能同时执行到中间的 use 步骤。&lt;/p&gt;&#xA;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;sequenceDiagram&#xA;    participant 主内存&#xA;    participant 工作内存A&#xA;    participant 线程A&#xA;    participant 工作内存B&#xA;    participant 线程B&#xA;&#xA;    rect rgba(255, 0, 0, 0.1)&#xA;        Note left of 线程A: 线程A操作&#xA;        线程A -&gt;&gt; 主内存: read(var)&#xA;        主内存 --&gt;&gt; 工作内存A: var=0&#xA;        线程A -&gt;&gt; 工作内存A: load(var)&#xA;        线程A -&gt;&gt; 工作内存A: assign(var, 1)&#xA;        线程A -&gt;&gt; 工作内存A: store(var)&#xA;        工作内存A --&gt;&gt; 主内存: 准备写入var=1&#xA;    end&#xA;&#xA;    rect rgba(0, 255, 0, 0.1)&#xA;        Note right of 线程B: 线程B操作（插入A的store→write之间）&#xA;        线程B -&gt;&gt; 主内存: read(var)（主内存仍为0）&#xA;        主内存 --&gt;&gt; 工作内存B: var=0&#xA;        线程B -&gt;&gt; 工作内存B: load(var)&#xA;        线程B -&gt;&gt; 工作内存B: assign(var, 1)&#xA;        线程B -&gt;&gt; 工作内存B: store(var)&#xA;        工作内存B --&gt;&gt; 主内存: 写入var=1&#xA;        主内存 --&gt;&gt; 线程B: write(var)完成&#xA;    end&#xA;&#xA;    rect rgba(255, 0, 0, 0.1)&#xA;        Note left of 线程A: 线程A完成写入（被覆盖）&#xA;        主内存 --&gt;&gt; 线程A: write(var)（最终var=1，预期为2）&#xA;    end&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;解决方式&lt;/strong&gt;：使用 &lt;code&gt;synchronized&lt;/code&gt; 或 &lt;code&gt;Lock&lt;/code&gt; 保证原子性，或使用 &lt;code&gt;AtomicInteger&lt;/code&gt; 等 CAS 操作。&lt;/p&gt;&#xA;&lt;h3 id=&#34;可见性问题&#34;&gt;可见性问题&#xA;&lt;/h3&gt;&lt;p&gt;线程 B 修改了变量，线程 A 可能仍然使用自己工作内存中的旧副本。原因：A 没有及时从主内存重新 read→load。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;volatile 解决可见性&lt;/strong&gt;：对 volatile 变量的写操作会立即执行 store→write 刷新到主内存，读操作会强制从主内存 read→load，而不是使用工作内存缓存的旧值。&lt;/p&gt;&#xA;&lt;pre class=&#34;mermaid&#34; style=&#34;visibility:hidden&#34;&gt;sequenceDiagram&#xA;    participant 主内存&#xA;    participant 工作内存A&#xA;    participant 线程A&#xA;    participant 工作内存B&#xA;    participant 线程B&#xA;&#xA;    rect rgba(0, 255, 0, 0.1)&#xA;        Note left of 线程A: 线程A操作（volatile变量）&#xA;        线程A -&gt;&gt; 主内存: read(var)&#xA;        主内存 --&gt;&gt; 工作内存A: var=0&#xA;        线程A -&gt;&gt; 工作内存A: load(var)&#xA;        线程A -&gt;&gt; 工作内存A: assign(var, 1)&#xA;        线程A -&gt;&gt; 工作内存A: store(var)&#xA;        工作内存A --&gt;&gt; 主内存: 立即写入var=1&#xA;        主内存 --&gt;&gt; 线程A: write(var)完成&#xA;    end&#xA;&#xA;    rect rgba(0, 0, 255, 0.1)&#xA;        Note right of 线程B: 线程B操作（强制读取最新值）&#xA;        线程B -&gt;&gt; 主内存: read(var)（必须读取var=1）&#xA;        主内存 --&gt;&gt; 工作内存B: var=1&#xA;        线程B -&gt;&gt; 工作内存B: load(var)&#xA;    end&lt;/pre&gt;&lt;h3 id=&#34;有序性问题&#34;&gt;有序性问题&#xA;&lt;/h3&gt;&lt;p&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:#75715e&#34;&gt;// 未正确使用 volatile 的版本&lt;/span&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;static&lt;/span&gt; Singleton instance;&#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; Singleton &lt;span style=&#34;color:#a6e22e&#34;&gt;getInstance&lt;/span&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; (instance &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&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;synchronized&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&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; (instance &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&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;                instance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Singleton();  &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;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; instance;&#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;instance = new Singleton()&lt;/code&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;/ol&gt;&#xA;&lt;p&gt;步骤 2 和 3 可能被重排序，导致另一个线程获得一个未初始化完成的对象。&lt;strong&gt;volatile 通过禁止指令重排序解决了这个问题&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四happens-before-规则&#34;&gt;四、happens-before 规则&#xA;&lt;/h2&gt;&lt;p&gt;happens-before 是 JMM 的核心规则，用于判断两个操作之间是否存在数据竞争：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;程序顺序规则&lt;/strong&gt;：一个线程中的每个操作 happens-before 该线程的后续操作&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;volatile 变量规则&lt;/strong&gt;：对 volatile 变量的写 happens-before 后续对该变量的读&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;锁规则&lt;/strong&gt;：解锁 happens-before 后续对同一把锁的加锁&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;传递性&lt;/strong&gt;：A happens-before B 且 B happens-before C → A happens-before C&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;线程启动规则&lt;/strong&gt;：Thread.start() happens-before 被启动线程中的任何操作&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;线程 join 规则&lt;/strong&gt;：线程中所有操作 happens-before 其他线程对该线程的 Thread.join() 成功返回&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五volatile-vs-synchronized-对比&#34;&gt;五、volatile vs synchronized 对比&#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;volatile&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;synchronized&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;保证&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;状态标记、单次写入&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;volatile 不能替代 synchronized&lt;/strong&gt;：volatile 仅保证可见性和有序性，不保证原子性（如 &lt;code&gt;count++&lt;/code&gt; 仍然有并发问题）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;final 也有可见性保证&lt;/strong&gt;：JMM 保证构造函数结束后，final 字段对其他线程可见（除非发生 this 引用逸出）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;happens-before 规则不是时间顺序&lt;/strong&gt;：它不要求物理时间上 A 先于 B 执行，只要求在语义上 A 的结果对 B 可见&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>JVM 问题排查</title>
            <link>https://xumf.net/blog/jvmissuesolution/</link>
            <pubDate>Sun, 12 Jul 2020 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/jvmissuesolution/</guid>
            <description>&lt;h3 id=&#34;可正常运行系统&#34;&gt;可正常运行系统：&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;通过&lt;code&gt;jmap&lt;/code&gt;来查看JVM中各个区域的使用情况&lt;/li&gt;&#xA;&lt;li&gt;通过&lt;code&gt;jstack&lt;/code&gt;来查看线程的运行情况，比如哪些线程阻塞、是否出现死锁&lt;/li&gt;&#xA;&lt;li&gt;通过j&lt;code&gt;stat&lt;/code&gt;来查看垃圾回收情况，特别是fullgc，如果发现fullgc比较频繁，那么就得进行调优&lt;/li&gt;&#xA;&lt;li&gt;通过各个命令的结果或者&lt;code&gt;jvisualvm&lt;/code&gt;等工具来进行分析&lt;/li&gt;&#xA;&lt;li&gt;首先：初步猜测频发发送fullgc的原因，如果频繁发生fullgc，但是又一直没有出现内存溢出，那么表示fullgc实际上回收了很多对象，所以这些对象最好能在younggc过程中直接回收掉，避免这些对象进入到老年代，对于这种情况，就要考虑这些存活时间不长的对象是不是比较大，导致年轻代放不下，直接进入到老年代，尝试加大年轻代的大小，如果改完之后，fullgc减少，则证明修改有效&lt;/li&gt;&#xA;&lt;li&gt;同时，还可以找到占用CPU最多的线程，定位到具体的方法，优化这个方法的执行，看是否能避免某些对象的创建，从而节省内存&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;运行中发生oom的系统&#34;&gt;运行中发生OOM的系统：&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;一般生产系统中都会设置当前系统发生了OOM时，生成当时的dump文件（&lt;code&gt;-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;我们可以利用&lt;code&gt;jvisualvm&lt;/code&gt;等工具来分析dump文件&lt;/li&gt;&#xA;&lt;li&gt;根据dump文件找到异常的实例对象和异常的线程（占用CPU高），定位到具体代码&lt;/li&gt;&#xA;&lt;li&gt;然后再进行详细的分析和调试&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>Kubernetes 深入浅出</title>
            <link>https://xumf.net/blog/kubernetes/</link>
            <pubDate>Tue, 24 Mar 2020 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/kubernetes/</guid>
            <description>&lt;h2 id=&#34;kubernetes-核心概念&#34;&gt;Kubernetes 核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;为什么需要-kubernetes&#34;&gt;为什么需要 Kubernetes？&#xA;&lt;/h3&gt;&lt;p&gt;容器化解决了环境一致性问题，但生产环境需要管理成百上千个容器——自动部署、扩缩容、负载均衡、服务发现、滚动更新。Kubernetes 提供了这些能力的声明式编排框架。&lt;/p&gt;&#xA;&lt;h3 id=&#34;架构总览&#34;&gt;架构总览&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌─────────────────────────────────────────┐&#xA;│              Control Plane              │&#xA;│  ┌──────────┐ ┌──────────┐ ┌─────────┐ │&#xA;│  │ API Svr  │ │Scheduler │ │Ctrl Mgr │ │&#xA;│  └────┬─────┘ └────┬─────┘ └────┬────┘ │&#xA;│       │            │            │       │&#xA;│  ┌────▼──────────────────────────▼────┐ │&#xA;│  │              etcd                  │ │&#xA;│  └───────────────────────────────────┘ │&#xA;└──────────────────┬──────────────────────┘&#xA;                   │&#xA;┌──────────────────▼──────────────────────┐&#xA;│               Node                      │&#xA;│  ┌──────────┐  ┌──────────┐ ┌────────┐ │&#xA;│  │ Kubelet  │  │Kube-Proxy│ │Runtime │ │&#xA;│  └────┬─────┘  └────┬─────┘ └───┬────┘ │&#xA;│       │             │           │       │&#xA;│  ┌────▼─────────────▼───────────▼────┐ │&#xA;│  │          Pods                     │ │&#xA;│  └──────────────────────────────────┘ │&#xA;└────────────────────────────────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;核心组件设计原理&#34;&gt;核心组件设计原理&#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;&lt;strong&gt;API Server&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;提供 RESTful API，是集群入口&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;所有组件只与 API Server 通信，避免组件间直接耦合——这是 K8s 的核心设计哲学：&lt;strong&gt;声明式 + 控制循环&lt;/strong&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;strong&gt;etcd&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;分布式 KV 存储，保存集群全部状态&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;基于 Raft 共识算法保证一致性。为什么选 etcd？强一致、watch 机制（支持控制器监听变更）、CNCF 项目&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;strong&gt;Scheduler&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;将 Pod 分配到最优 Node&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;筛选（Predicates）→ 打分（Priorities）两阶段算法，而非简单轮询，因为需要考虑资源、亲和性、污点等多维约束&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;strong&gt;Controller Manager&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;运行各种控制器（Deployment、Node、Endpoints 等）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;控制循环模式（Reconciliation Loop）：期望状态 vs 实际状态，不断调谐直到一致&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;strong&gt;Kubelet&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;管理 Pod 生命周期&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;节点上的 Agent，负责创建/删除容器、健康检查、上报节点状态&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;strong&gt;Kube-Proxy&lt;/strong&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;维护 iptables/IPVS 规则，将 Service IP 转发到后端 Pod&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h4 id=&#34;关键设计声明式-api--控制循环&#34;&gt;关键设计：声明式 API + 控制循环&#xA;&lt;/h4&gt;&lt;p&gt;K8s 的设计核心不是命令式（&amp;ldquo;启动 3 个 nginx&amp;rdquo;），而是声明式（&amp;ldquo;确保有 3 个 nginx 在运行&amp;rdquo;）。用户提交期望状态（通过 YAML），控制器监听 API Server 的变化，不断调谐直到实际状态与期望状态一致。这种模式的好处：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;自动恢复：Pod 挂了，ReplicaSet 控制器自动补一个&lt;/li&gt;&#xA;&lt;li&gt;幂等：同样的 YAML 应用多次结果一致&lt;/li&gt;&#xA;&lt;li&gt;可审计：所有变更记录在 etcd 中&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;核心资源对象详解&#34;&gt;核心资源对象详解&#xA;&lt;/h2&gt;&lt;h3 id=&#34;pod&#34;&gt;Pod&#xA;&lt;/h3&gt;&lt;p&gt;Pod 是最小调度单元。为什么不是容器？因为有些场景多个容器需要共享网络栈（如 Sidecar 模式），K8s 将它们打包为 Pod，共享 IP、端口、存储卷。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Pod 生命周期&lt;/strong&gt;：&lt;code&gt;Pending → Running → Succeeded/Failed → Unknown&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;关键阶段说明：&#xA;- Pending：API Server 已接受，但 Pod 尚未调度到 Node（或镜像拉取中）&#xA;- Running：至少有一个容器在运行&#xA;- Unknown：Node 失联（kubelet 停止上报心跳）&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;deployment&#34;&gt;Deployment&#xA;&lt;/h3&gt;&lt;p&gt;Deployment 管理 ReplicaSet，ReplicaSet 管理 Pod。为什么中间加一层 ReplicaSet？为了实现&lt;strong&gt;滚动更新与回滚&lt;/strong&gt;——每发布一次，创建一个新 RS，逐步扩容新 RS 并缩容旧 RS，回滚时直接指回旧 RS。&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;apps/v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Deployment&lt;/span&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;metadata&lt;/span&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;nginx-deployment&lt;/span&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;spec&lt;/span&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;replicas&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;revisionHistoryLimit&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;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;strategy&lt;/span&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;RollingUpdate&lt;/span&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;rollingUpdate&lt;/span&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;maxSurge&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;                   &lt;span style=&#34;color:#75715e&#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;maxUnavailable&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;selector&lt;/span&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;matchLabels&lt;/span&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;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&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;template&lt;/span&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;metadata&lt;/span&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;labels&lt;/span&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;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&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;spec&lt;/span&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;containers&lt;/span&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;nginx&lt;/span&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;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx:1.14.2&lt;/span&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;ports&lt;/span&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;containerPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&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;resources&lt;/span&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;requests&lt;/span&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;cpu&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;100m&lt;/span&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;memory&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;128Mi&lt;/span&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;limits&lt;/span&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;cpu&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;500m&lt;/span&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;memory&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;512Mi&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;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;创建新 ReplicaSet（副本数为 0）&lt;/li&gt;&#xA;&lt;li&gt;新 RS +1，旧 RS -1（maxSurge=1, maxUnavailable=0 意味着始终保持 3 个可用 Pod）&lt;/li&gt;&#xA;&lt;li&gt;重复直到新 RS 达到 3，旧 RS 缩到 0&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;service&#34;&gt;Service&#xA;&lt;/h3&gt;&lt;p&gt;Pod 的 IP 不固定（重启、扩缩容后会变），Service 提供稳定的访问入口。实现方式：kube-proxy 在节点上维护 iptables/IPVS 规则。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Service 类型选择&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;访问范围&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;ClusterIP&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;集群内&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;iptables/IPVS 转发&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;NodePort&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;集群外（节点 IP:端口）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;每个节点监听端口 → iptables&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;开发调试、无 LB&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;LoadBalancer&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;公网&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;云厂商 LB + NodePort&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;ExternalName&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;DNS 映射&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;CoreDNS 返回 CNAME&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;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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;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;metadata&lt;/span&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;nginx-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;spec&lt;/span&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;selector&lt;/span&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;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&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;ports&lt;/span&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;protocol&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;TCP&lt;/span&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;80&lt;/span&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;targetPort&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&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;ClusterIP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;configmap-和-secret&#34;&gt;ConfigMap 和 Secret&#xA;&lt;/h3&gt;&lt;p&gt;为什么需要 ConfigMap？将配置与容器镜像解耦，镜像不变、配置可变。&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ConfigMap&lt;/span&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;metadata&lt;/span&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;app-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;data&lt;/span&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.yml&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    server:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      port: 8080&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    database:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      url: jdbc:mysql://db:3306/app&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Secret 存储敏感信息，数据以 Base64 编码（非加密——需要配合 RBAC 和加密存储）。&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Secret&lt;/span&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;metadata&lt;/span&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;db-secret&lt;/span&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;Opaque&lt;/span&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;data&lt;/span&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;YWRtaW4=&lt;/span&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;MWYyZDFlMmU2N2Rm&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;：ConfigMap/Secret 更新后，Pod 中的环境变量不会自动更新，只有通过 Volume 挂载的方式才会自动同步（默认约 60 秒）。&lt;/p&gt;&#xA;&lt;h2 id=&#34;网络模型&#34;&gt;网络模型&#xA;&lt;/h2&gt;&lt;p&gt;K8s 网络模型的核心约定——&lt;strong&gt;每个 Pod 都有独立 IP，Pod 之间可以直接通信&lt;/strong&gt;（无需 NAT）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;cni-插件原理&#34;&gt;CNI 插件原理&#xA;&lt;/h3&gt;&lt;p&gt;K8s 不自己实现网络，而是通过 CNI（Container Network Interface）插件接入。工作流程：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Pod 创建 → kubelet 调用 CNI 插件 → 插件创建 veth pair → 一端 Pod 内，一端连到网桥/路由&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;常见 CNI 对比：&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;CNI&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;Flannel&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;VXLAN/UDP&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;Calico&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;BGP + iptables&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;纯三层，性能好，支持 NetworkPolicy&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;Cilium&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;eBPF&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;性能极高，支持 L7 策略，但要求内核 5.8+&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;Weave&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;VXLAN + fastdp&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;Service 网络&lt;/strong&gt;：ClusterIP 通过 kube-proxy 的 iptables/IPVS 规则将虚拟 IP 映射到后端 Pod。IPVS 比 iptables 更适合大规模集群（iptables 的规则复杂度为 O(n)，IPVS 为 O(1)）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt;：CoreDNS 为 Service 解析域名，格式为 &lt;code&gt;&amp;lt;service&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;存储管理&#34;&gt;存储管理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;volumes-类型与选择&#34;&gt;Volumes 类型与选择&#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;emptyDir&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Pod 生命周期&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;临时缓存、Sidecar 数据交换&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;hostPath&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Node 生命周期&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;PersistentVolumeClaim&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;独立于 Pod&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;pvpvc-设计原理&#34;&gt;PV/PVC 设计原理&#xA;&lt;/h3&gt;&lt;p&gt;为什么设计 PV 和 PVC 两层抽象？将&lt;strong&gt;存储的提供&lt;/strong&gt;和&lt;strong&gt;存储的使用&lt;/strong&gt;分离：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;PV&lt;/strong&gt;：由集群管理员预先创建或通过 StorageClass 动态供应&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;PVC&lt;/strong&gt;：用户声明存储需求（大小、访问模式），与 PV 匹配后绑定&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:#75715e&#34;&gt;# PV&lt;/span&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PersistentVolume&lt;/span&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;metadata&lt;/span&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;pv001&lt;/span&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;spec&lt;/span&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;capacity&lt;/span&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;storage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5Gi&lt;/span&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;accessModes&lt;/span&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;ReadWriteOnce&lt;/span&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;hostPath&lt;/span&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;/data&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;# PVC&lt;/span&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PersistentVolumeClaim&lt;/span&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;metadata&lt;/span&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;myclaim&lt;/span&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;spec&lt;/span&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;accessModes&lt;/span&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;ReadWriteOnce&lt;/span&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;resources&lt;/span&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;requests&lt;/span&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;storage&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3Gi&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;PV 回收策略&lt;/strong&gt;：&lt;code&gt;Retain&lt;/code&gt;（管理员手动回收）→ 生产环境推荐 / &lt;code&gt;Delete&lt;/code&gt;（自动删除）→ 动态供应场景 / &lt;code&gt;Recycle&lt;/code&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;Scheduler 对每个待调度 Pod 执行两步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Predicates（筛选）&lt;/strong&gt;：过滤不满足条件的 Node。包括：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;PodFitsResources&lt;/code&gt;：节点资源足够&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;MatchNodeSelector&lt;/code&gt;：匹配 &lt;code&gt;nodeSelector&lt;/code&gt; 标签&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;PodToleratesNodeTaints&lt;/code&gt;：Pod 能容忍 Node 的污点&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CheckNodePortConflict&lt;/code&gt;：端口不冲突&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CheckNodeAffinity&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;Priorities（打分）&lt;/strong&gt;：对候选 Node 按策略评分：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;LeastRequestedPriority&lt;/code&gt;：资源利用率低的 Node 得分高（分散 Pod）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;BalancedResourceAllocation&lt;/code&gt;：CPU 和内存均衡使用&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ImageLocalityPriority&lt;/code&gt;：Pod 镜像已有的 Node 得分高&lt;/li&gt;&#xA;&lt;li&gt;NodeAffinity、TaintToleration 等优先级&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&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-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;# nodeSelector：简单的标签匹配&lt;/span&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;spec&lt;/span&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;nodeSelector&lt;/span&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;disktype&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ssd&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:#f92672&#34;&gt;spec&lt;/span&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;affinity&lt;/span&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;nodeAffinity&lt;/span&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;requiredDuringSchedulingIgnoredDuringExecution&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;nodeSelectorTerms&lt;/span&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;matchExpressions&lt;/span&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;key&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;disktype&lt;/span&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;operator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;In&lt;/span&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;values&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ssd&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;preferredDuringSchedulingIgnoredDuringExecution&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;weight&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&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;preference&lt;/span&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;matchExpressions&lt;/span&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;key&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;zone&lt;/span&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;operator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;In&lt;/span&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;values&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;pod-亲和性与反亲和性&#34;&gt;Pod 亲和性与反亲和性&#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;spec&lt;/span&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;affinity&lt;/span&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;podAntiAffinity&lt;/span&gt;:  &lt;span style=&#34;color:#75715e&#34;&gt;# 确保同一服务的 Pod 分散在不同节点&lt;/span&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;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&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;labelSelector&lt;/span&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;matchLabels&lt;/span&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;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nginx&lt;/span&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;topologyKey&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kubernetes.io/hostname&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;topologyKey&lt;/strong&gt; 指定了&amp;quot;分散的范围&amp;quot;——这里是 &lt;code&gt;hostname&lt;/code&gt;，即不同宿主机。&lt;/p&gt;&#xA;&lt;h3 id=&#34;污点与容忍&#34;&gt;污点与容忍&#xA;&lt;/h3&gt;&lt;p&gt;污点（Taint）阻止 Pod 调度到特定 Node，容忍（Toleration）允许 Pod&amp;quot;忍受&amp;quot;污点。&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:#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:#75715e&#34;&gt;# kubectl taint nodes node1 key=value:NoSchedule&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;# Pod 容忍&lt;/span&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;spec&lt;/span&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;tolerations&lt;/span&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;key&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;key1&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;operator&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Equal&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;value&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;value1&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;effect&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NoSchedule&amp;#34;&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;NoSchedule&lt;/code&gt;（不调度新 Pod）/ &lt;code&gt;PreferNoSchedule&lt;/code&gt;（尽量不调度）/ &lt;code&gt;NoExecute&lt;/code&gt;（驱逐已有 Pod）&lt;/p&gt;&#xA;&lt;h2 id=&#34;安全机制&#34;&gt;安全机制&#xA;&lt;/h2&gt;&lt;h3 id=&#34;rbac&#34;&gt;RBAC&#xA;&lt;/h3&gt;&lt;p&gt;K8s 的授权体系基于 RBAC（最小权限原则）。&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;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io/v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Role&lt;/span&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;metadata&lt;/span&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;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;default&lt;/span&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;pod-reader&lt;/span&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;rules&lt;/span&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;apiGroups&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;resources&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pods&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;verbs&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;get&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;watch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;list&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;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io/v1&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;RoleBinding&lt;/span&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;metadata&lt;/span&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;read-pods&lt;/span&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;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;default&lt;/span&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;subjects&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;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;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;developer&lt;/span&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;apiGroup&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io&lt;/span&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;roleRef&lt;/span&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;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Role&lt;/span&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;pod-reader&lt;/span&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;apiGroup&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io&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;ClusterRole vs Role&lt;/strong&gt;：Role 作用于特定 Namespace，ClusterRole 作用于集群范围。&lt;/p&gt;&#xA;&lt;h2 id=&#34;高可用设计&#34;&gt;高可用设计&#xA;&lt;/h2&gt;&lt;h3 id=&#34;master-高可用&#34;&gt;Master 高可用&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Load Balancer → API Server × 3 → etcd cluster × 3（奇数节点）&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;etcd 基于 Raft 协议，3 节点允许 1 个故障，5 节点允许 2 个故障。Scheduler 和 Controller Manager 通过 Leader Election 选主。&lt;/p&gt;&#xA;&lt;h3 id=&#34;pod-高可用&#34;&gt;Pod 高可用&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Deployment 多副本 + 反亲和性确保跨节点分布&lt;/li&gt;&#xA;&lt;li&gt;PDB（PodDisruptionBudget）确保更新时最少存活副本数&lt;/li&gt;&#xA;&lt;li&gt;HPA 根据指标自动伸缩&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;节点故障处理&#34;&gt;节点故障处理&#xA;&lt;/h3&gt;&lt;p&gt;Node 失联后：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;默认 40 秒后 Node 变为 &lt;code&gt;NotReady&lt;/code&gt;（&lt;code&gt;node-monitor-period&lt;/code&gt; 5 秒 × &lt;code&gt;node-monitor-grace-period&lt;/code&gt; 40 秒 × 8 次失败）&lt;/li&gt;&#xA;&lt;li&gt;Controller Manager 的 NodeLifecycleController 驱逐 Pod（&lt;code&gt;pod-eviction-timeout&lt;/code&gt; 默认 5 分钟）&lt;/li&gt;&#xA;&lt;li&gt;被驱逐的 Pod 在其他 Node 上重建&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;&#xA;&lt;p&gt;&lt;strong&gt;Pod 一直 Pending&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;kubectl describe pod &amp;lt;name&amp;gt;&lt;/code&gt; 查看 Events&lt;/li&gt;&#xA;&lt;li&gt;常见原因：节点资源不足、PVC 未绑定、镜像拉取失败、端口冲突&lt;/li&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;kubectl get nodes&lt;/code&gt; 是否有 Ready 节点&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Pod 不断 CrashLoopBackOff&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;kubectl logs &amp;lt;pod&amp;gt;&lt;/code&gt; 查看日志&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;kubectl logs &amp;lt;pod&amp;gt; --previous&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;Node 一直 NotReady&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;排查 kubelet 是否运行：&lt;code&gt;systemctl status kubelet&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;检查 kubelet 日志：&lt;code&gt;journalctl -u kubelet -f&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;docker info&lt;/code&gt;（或 &lt;code&gt;crictl info&lt;/code&gt;）确认容器运行时正常&lt;/li&gt;&#xA;&lt;li&gt;检查磁盘空间：&lt;code&gt;df -h&lt;/code&gt;（磁盘满会导致 Node NotReady）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Service 不通&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 Endpoint：&lt;code&gt;kubectl get endpoints &amp;lt;service&amp;gt;&lt;/code&gt;——为空说明 Pod 未匹配到 Service selector&lt;/li&gt;&#xA;&lt;li&gt;检查 CoreDNS：&lt;code&gt;kubectl run -it test --image=busybox -- wget &amp;lt;service&amp;gt;&lt;/code&gt;——DNS 解析是否正常&lt;/li&gt;&#xA;&lt;li&gt;检查 kube-proxy 能否正常工作：&lt;code&gt;iptables-save | grep &amp;lt;service-name&amp;gt;&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;检查 PV/PVC 状态：&lt;code&gt;kubectl get pv,pvc&lt;/code&gt;——Pending 说明未绑定&lt;/li&gt;&#xA;&lt;li&gt;检查 StorageClass 是否正确创建——动态供应时需要默认 StorageClass&lt;/li&gt;&#xA;&lt;li&gt;检查宿主机目录权限——hostPath 场景需确认目录存在且权限正确&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;etcd 性能问题&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;etcdctl check perf&lt;/code&gt; 检查读写延迟&lt;/li&gt;&#xA;&lt;li&gt;避免单 etcd 成员存储过大（建议 8GB 限制）&lt;/li&gt;&#xA;&lt;li&gt;避免频繁大量写入（如频繁创建/删除 Pod）&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>HBase 深入浅出</title>
            <link>https://xumf.net/blog/hbase/</link>
            <pubDate>Wed, 15 Aug 2018 15:43:54 +0800</pubDate>
            <guid>https://xumf.net/blog/hbase/</guid>
            <description>&lt;h2 id=&#34;为什么需要-hbase&#34;&gt;为什么需要 HBase？&#xA;&lt;/h2&gt;&lt;p&gt;传统关系型数据库在数据量达到 TB 级、写入吞吐量达到每秒百万行时会出现瓶颈：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;MySQL 分库分表后跨节点 Join/聚合困难&lt;/li&gt;&#xA;&lt;li&gt;写入吞吐受限于单机 B+Tree 的随机写性能&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;HBase 的解决思路：&lt;strong&gt;LSM-Tree + 列式存储 + 水平扩展&lt;/strong&gt;。它将随机写转为顺序写（先写内存再刷盘），通过 Region 自动分裂实现水平扩展。&lt;/p&gt;&#xA;&lt;h2 id=&#34;1-hbase-核心组件&#34;&gt;1. HBase 核心组件&#xA;&lt;/h2&gt;&lt;h3 id=&#34;11-hmaster&#34;&gt;1.1 HMaster&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;源码路径&lt;/strong&gt;：&lt;code&gt;org.apache.hadoop.hbase.master.HMaster&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;核心职责：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;元数据管理&lt;/strong&gt;：处理 DDL（创建/删除/修改表），维护 &lt;code&gt;hbase:meta&lt;/code&gt; 表&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;负载均衡&lt;/strong&gt;：监控 RegionServer 负载，分配/迁移 Region&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;故障恢复&lt;/strong&gt;：RegionServer 宕机时重新分配其 Region&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;启动流程&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;连接 ZooKeeper，尝试创建 HMaster 临时节点（选主）&lt;/li&gt;&#xA;&lt;li&gt;加载 &lt;code&gt;hbase:meta&lt;/code&gt; 表，获取所有 Region 分布信息&lt;/li&gt;&#xA;&lt;li&gt;启动后台线程：LoadBalancer（定期均衡 Region）、CatalogJanitor（清理 meta 中的无效条目）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;高可用机制&lt;/strong&gt;：通过 ZooKeeper 选举，同一时间只有一个活跃 HMaster。Standby HMaster 监听活跃节点，发现 znode 消失后立刻尝试成为主。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;面试常见问题：HMaster 宕机后 HBase 还能工作吗？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;可以。读写操作由 RegionServer 直接处理，HMaster 只负责 DDL 和负载均衡。已有表的读写不受影响，但无法创建新表或修改表结构。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;12-regionserver&#34;&gt;1.2 RegionServer&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;源码路径&lt;/strong&gt;：&lt;code&gt;org.apache.hadoop.hbase.regionserver.HRegionServer&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;核心职责与架构：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌─────────────────── RegionServer ───────────────────┐&#xA;│  ┌────────┐  ┌────────┐  ┌────────┐                │&#xA;│  │ Region1 │  │ Region2 │  │ Region3 │  ← 每个 Region 负责一段 RowKey 范围&#xA;│  └────┬───┘  └────┬───┘  └────┬───┘                │&#xA;│       │           │           │                     │&#xA;│  ┌────▼───────────▼───────────▼─────┐               │&#xA;│  │  Store(ColumnFamily: info)       │               │&#xA;│  │  ┌────────────┐ ┌─────────────┐ │               │&#xA;│  │  │ MemStore   │ │ StoreFile   │ │               │&#xA;│  │  │(SkipList)  │ │ (HFile × N) │ │               │&#xA;│  │  └────────────┘ └─────────────┘ │               │&#xA;│  ├──────────────────────────────────┤               │&#xA;│  │ BlockCache (LruBlockCache)       │               │&#xA;│  │ WAL (Write Ahead Log → HDFS)    │               │&#xA;│  └──────────────────────────────────┘               │&#xA;└────────────────────────────────────────────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;写流程详解&#34;&gt;写流程详解&#xA;&lt;/h4&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Client → RegionServer&#xA;  1️⃣ 写入 WAL（HDFS，保证不丢数据）&#xA;  2️⃣ 写入 MemStore（ConcurrentSkipListMap，有序）&#xA;  ─── 返回成功给客户端 ───&#xA;  3️⃣ 后台 Flush 线程：当 MemStore 达到阈值（128MB）→ 生成 HFile&#xA;  4️⃣ 后台 Compaction：合并小 HFile，删除已删除/过期的数据&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;写入为什么先写 WAL 再写 MemStore？&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;WAL 在 HDFS 上（多副本），RegionServer 宕机后可以通过 WAL 恢复 MemStore 中未刷盘的数据&lt;/li&gt;&#xA;&lt;li&gt;WAL 使用顺序写（HDFS Append），性能远高于随机写&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;为什么 MemStore 用 ConcurrentSkipListMap？&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;数据按 RowKey 排序存储——HFile 要求数据有序，这样可以顺序写入&lt;/li&gt;&#xA;&lt;li&gt;ConcurrentSkipListMap 支持 O(log N) 的插入和查找，同时线程安全&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;读流程详解&#34;&gt;读流程详解&#xA;&lt;/h4&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Client → RegionServer&#xA;  1️⃣ 查询 BlockCache（LruBlockCache，缓存热点 HFile Block）&#xA;  2️⃣ 未命中 → 查询 MemStore（未刷盘的最新数据）&#xA;  3️⃣ 未命中 → 查询 HFile（Bloom Filter 先过滤，跳过不含该 RowKey 的文件）&#xA;  4️⃣ 合并所有结果（MemStore + 多个 HFile），按时间戳取最新版本&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;BlockCache vs MemStore&lt;/strong&gt;：MemStore 存的是还没写入 HFile 的数据（写缓存），BlockCache 缓存已读过的 HFile Block（读缓存）。两者分离，避免写操作影响读缓存。&lt;/p&gt;&#xA;&lt;h3 id=&#34;13-region&#34;&gt;1.3 Region&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;源码路径&lt;/strong&gt;：&lt;code&gt;org.apache.hadoop.hbase.regionserver.HRegion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Region 按 RowKey 范围水平切分表数据。每个 Region 包含多个 Store（每列族一个）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Region 分裂流程&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. RegionServer 检测 Region 大小超过阈值 (hbase.hregion.max.filesize, 默认 10GB)&#xA;2. 将 Region 下线（短暂不可用）&#xA;3. 找到 Region 的中点 RowKey，拆分为两个子 Region&#xA;4. 在 hbase:meta 中更新 Region 信息&#xA;5. 两个子 Region 上线，客户端刷新 meta 缓存后路由到新 Region&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;分裂对读写的影响：分裂期间该 Region 短暂不可用（毫秒级），通过 WAL 和 Meta 更新保证一致性。&lt;/p&gt;&#xA;&lt;h3 id=&#34;14-walwrite-ahead-log&#34;&gt;1.4 WAL（Write Ahead Log）&#xA;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;源码路径&lt;/strong&gt;：&lt;code&gt;org.apache.hadoop.hbase.wal.WAL&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;每次写入流程：&#xA;1. RegionServer 将写入操作封装为 WALEdit&#xA;2. 通过 FSHLog 写入 HDFS 上的 WAL 文件（顺序追加，高性能）&#xA;3. 写入成功后，再写入 MemStore&#xA;4. 当 MemStore 刷盘成功 → 该部分 WAL 可截断&#xA;&#xA;崩溃恢复流程：&#xA;1. RegionServer 宕机 → HMaster 感知（通过 ZooKeeper Session 超时）&#xA;2. HMaster 将该 RS 上的 Region 重新分配给其他 RS&#xA;3. 新 RS 加载 WAL，回放数据到 MemStore&#xA;4. MemStore 刷盘后，数据恢复完成&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;WAL 性能优化&lt;/strong&gt;：默认是同步写入（每条写入都 fsync），可通过 &lt;code&gt;hbase.wal.hsync=false&lt;/code&gt; 改为异步（风险：RegionServer 进程级崩溃可能丢失少量数据）。&lt;/p&gt;&#xA;&lt;h2 id=&#34;2-hbase-读写流程深入&#34;&gt;2. HBase 读写流程深入&#xA;&lt;/h2&gt;&lt;h3 id=&#34;21-完整写入流程含客户端侧&#34;&gt;2.1 完整写入流程（含客户端侧）&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. 客户端从 hbase:meta 获取 RowKey 对应的 RegionServer&#xA;2. 客户端直连该 RegionServer（无中间代理）&#xA;3. RegionServer 接收请求 → 写入 WAL（多副本到 HDFS）&#xA;4. 写入 MemStore（ConcurrentSkipListMap）&#xA;5. 返回成功给客户端&#xA;6. 异步 Flush 线程在 MemStore 达到 128MB（`hbase.hregion.memstore.flush.size`）时：&#xA;   ├─ 在窗口中保持最新写入（不阻塞）&#xA;   ├─ 将当前 MemStore 快照转换为不可变数据&#xA;   └─ 写入 HFile（按照 RowKey 顺序）&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;数据一致性保证&lt;/strong&gt;：WAL（HDFS 3 副本）+ MemStore 的 Snapshot + Flush 机制确保即使 RS 宕机也不会丢数据。&lt;/p&gt;&#xA;&lt;h3 id=&#34;22-完整读取流程&#34;&gt;2.2 完整读取流程&#xA;&lt;/h3&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1. 客户端从 hbase:meta 获取 RowKey 对应的 RegionServer&#xA;2. 客户端直连该 RegionServer&#xA;3. RegionServer 创建 scanner：&#xA;   ├─ 构建读取路径：MemStore + BlockCache + 所有相关 HFile&#xA;   └─ 合并结果（按 RowKey + TimeStamp + Type 排序）&#xA;4. 返回查询结果（逐行或批量）&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;读性能优化&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Bloom Filter&lt;/strong&gt;：跳过不含目标 RowKey 的 HFile，减少 I/O。布隆过滤器会占用内存（每个 HFile 约 1% 额外空间），但可大幅提升随机读性能&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;BlockCache&lt;/strong&gt;：缓存热点 HFile Block（Block 默认 64KB），顺序读取时命中率高&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;预分区（Pre-splitting）&lt;/strong&gt;：建表时指定 Region 数量和 split 点，避免单 Region 热点&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;压缩&lt;/strong&gt;：Snappy 压缩 HFile（CPU 开销小，压缩比约 2:1），减少磁盘 I/O&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;3-高级特性&#34;&gt;3. 高级特性&#xA;&lt;/h2&gt;&lt;h3 id=&#34;31-协处理器coprocessor&#34;&gt;3.1 协处理器（Coprocessor）&#xA;&lt;/h3&gt;&lt;p&gt;类似数据库的触发器（Observer）和存储过程（Endpoint）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Observer&lt;/strong&gt;：拦截 HBase 操作，在执行前后注入自定义逻辑。&lt;/p&gt;&#xA;&lt;p&gt;应用场景：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;二级索引&lt;/strong&gt;：Put 操作时写入索引表（Observer 拦截 postPut）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;权限校验&lt;/strong&gt;：Get 操作前检查用户权限（Observer 拦截 preGet）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;审计日志&lt;/strong&gt;：记录所有 DML 操作&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Endpoint&lt;/strong&gt;：在 RegionServer 上执行聚合计算，避免客户端拉回大量数据。&lt;/p&gt;&#xA;&lt;p&gt;场景示例：统计某个表的总行数——不通过 Endpoint 的话需要 Scan 全表拉回客户端，通过 Endpoint 各 Region 并行统计后返回汇总结果。&lt;/p&gt;&#xA;&lt;h3 id=&#34;32-压缩与编码&#34;&gt;3.2 压缩与编码&#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;CPU 开销&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;GZIP&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;Snappy&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;中（~2:1）&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;LZO&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;兼容性差（需安装 native lib）&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;ZSTD&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;JDK 11+，Facebook 开发&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&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-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;create &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mytable&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; NAME &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cf&amp;#39;&lt;/span&gt;, COMPRESSION &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;SNAPPY&amp;#39;&lt;/span&gt; &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;&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;alter &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mytable&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; NAME &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cf&amp;#39;&lt;/span&gt;, COMPRESSION &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;GZ&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#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;4-实战排查&#34;&gt;4. 实战排查&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;RegionServer 内存溢出（OOM）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;症状：RS 进程消失，HMaster 重新分配 Region&lt;/li&gt;&#xA;&lt;li&gt;检查 MemStore 大小：&lt;code&gt;hbase.hregion.memstore.flush.size&lt;/code&gt; × Region 数量 = RS 写缓冲区总量&lt;/li&gt;&#xA;&lt;li&gt;通常原因为 Region 过多导致 MemStore 总和超过 RS 堆内存——降低 &lt;code&gt;hbase.regionserver.global.memstore.size&lt;/code&gt;（默认 0.4，即 40% 堆内存）&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;BlockCache 命中率低：增大 &lt;code&gt;hfile.block.cache.size&lt;/code&gt;（默认 0.4）&lt;/li&gt;&#xA;&lt;li&gt;HFile 数量过多：触发 Major Compaction 合并（但 Major Compaction 期间 I/O 压力大）&lt;/li&gt;&#xA;&lt;li&gt;Bloom Filter 未开启：建表时 &lt;code&gt;BLOOMFILTER =&amp;gt; &#39;ROW&#39;&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;Region 热点&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;原因：RowKey 设计不合理，顺序递增导致所有写请求打在一个 Region 上&lt;/li&gt;&#xA;&lt;li&gt;解决方案：RowKey 加盐（前缀 hash）——如 &lt;code&gt;MD5(id).substring(0,4) + 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;Major Compaction 影响读写&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Major Compaction 合并所有 HFile，I/O 消耗大&lt;/li&gt;&#xA;&lt;li&gt;建议在低峰期触发：&lt;code&gt;hbase.hregion.majorcompaction&lt;/code&gt; 设置为 0（关闭自动），通过 crontab 手动触发&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;ZooKeeper Session 超时导致 RegionServer 被误判宕机&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 GC 日志——长时间的 Full GC 可能让 ZK 认为 RS 失联&lt;/li&gt;&#xA;&lt;li&gt;调大 &lt;code&gt;zookeeper.session.timeout&lt;/code&gt;（默认 90 秒），或缩短 GC 暂停时间&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item><item>
            <title>垃圾回收器</title>
            <link>https://xumf.net/blog/garbagecollector/</link>
            <pubDate>Wed, 18 Jul 2018 15:43:54 +0800</pubDate>
            <guid>https://xumf.net/blog/garbagecollector/</guid>
            <description>&lt;h2 id=&#34;一jvm-垃圾回收器概述&#34;&gt;一、JVM 垃圾回收器概述&#xA;&lt;/h2&gt;&lt;p&gt;常见的垃圾回收器：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Serial GC&lt;/li&gt;&#xA;&lt;li&gt;Parallel GC（Throughput GC）&lt;/li&gt;&#xA;&lt;li&gt;CMS GC（Concurrent Mark Sweep）&lt;/li&gt;&#xA;&lt;li&gt;G1 GC（Garbage First）&lt;/li&gt;&#xA;&lt;li&gt;ZGC（Z Garbage Collector）&lt;/li&gt;&#xA;&lt;li&gt;Shenandoah GC&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;二垃圾回收器的特点与回收流程&#34;&gt;二、垃圾回收器的特点与回收流程&#xA;&lt;/h2&gt;&lt;h3 id=&#34;衡量-gc-优劣的三个核心指标&#34;&gt;衡量 GC 优劣的三个核心指标&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;吞吐量（Throughput）&lt;/strong&gt;：用户代码运行时间 /（用户代码运行时间 + GC 时间）。越高越好。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;暂停时间（Pause Time / Latency）&lt;/strong&gt;：GC 时应用线程暂停的时间。越短越好。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存占用（Footprint）&lt;/strong&gt;：GC 额外消耗的内存（如 G1 的 RSet、ZGC 的染色指针）。越少越好。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这三者不可能同时优化——任何 GC 都在三者间做取舍。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-serial-gc&#34;&gt;1. Serial GC&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：单线程，回收时全部 STW&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么存在&lt;/strong&gt;：单核 CPU 或小型应用场景，多线程反而有额外开销&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;新生代：复制算法（Copying）&lt;/li&gt;&#xA;&lt;li&gt;老年代：标记-整理算法（Mark-Compact）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;code&gt;-XX:+UseSerialGC&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;何时选它&lt;/strong&gt;：堆小于 100MB、单核 CPU。其他情况不推荐。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2-parallel-gcthroughput-gc&#34;&gt;2. Parallel GC（Throughput GC）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：多线程，目标是最大化吞吐量，但 STW 时间较长&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;设计目标&lt;/strong&gt;：&amp;ldquo;只要暂停时间在可接受范围内，吞吐量越高越好&amp;rdquo;&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;老年代：标记-整理算法（多线程）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：多核 CPU、对延迟要求不高的批处理/数据分析任务&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseParallelGC&lt;/code&gt;：启用&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ParallelGCThreads&lt;/code&gt;：并行 GC 线程数（默认 = CPU 核心数）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt;：期望最大暂停时间（不是硬保证，默认无）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:GCTimeRatio&lt;/code&gt;：吞吐量目标（默认 99，即允许 1% 时间花在 GC 上）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3-cms-gcconcurrent-mark-sweep&#34;&gt;3. CMS GC（Concurrent Mark Sweep）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：并发收集老年代，尽量减少 STW 时间&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么选 CMS&lt;/strong&gt;：对于 Web 服务等延迟敏感应用，每次 Full GC 暂停几秒钟不可接受。CMS 让大部分 GC 工作与应用线程并发。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;初始标记（STW）&lt;/strong&gt;：标记 GC Roots 直接关联的对象——&lt;strong&gt;快速&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发标记&lt;/strong&gt;：从 GC Roots 开始遍历所有引用——&lt;strong&gt;与应用并发&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重新标记（STW）&lt;/strong&gt;：修正并发标记期间引用变化导致的漏标——&lt;strong&gt;较快&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发清除&lt;/strong&gt;：清除不可达对象——&lt;strong&gt;与应用并发&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&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;：使用标记-清除算法，老年代越来越碎片化 → 最终触发 Full GC 且无法避免长时间 STW&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CPU 敏感&lt;/strong&gt;：并发阶段抢占 CPU，应用吞吐量下降&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;浮动垃圾&lt;/strong&gt;：并发标记期间新产生的垃圾本次无法回收&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Promotion Failed&lt;/strong&gt;：新生代对象晋升老年代时无连续空间 → Full GC&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;-XX:+UseConcMarkSweepGC&lt;/code&gt;：启用（JDK 9 后已废弃，JDK 14 移除）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:CMSInitiatingOccupancyFraction&lt;/code&gt;：触发 CMS 的老年代使用率阈值（默认 68%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseCMSCompactAtFullCollection&lt;/code&gt;：Full GC 时整理内存&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:CMSFullGCsBeforeCompaction&lt;/code&gt;：多少次 Full GC 后进行一次整理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么被废弃&lt;/strong&gt;：G1 在延迟和吞吐量之间的平衡表现更好，且 CMS 无法解决碎片化和浮动垃圾问题。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4-g1-gcgarbage-first&#34;&gt;4. G1 GC（Garbage First）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：面向大堆、多核的服务端 GC。将堆划分为多个 Region，优先回收垃圾最多的 Region（&amp;ldquo;Garbage First&amp;rdquo; 名字的由来）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;设计思路&lt;/strong&gt;：不要求一次回收整个堆，而是分批次回收每个 Region，通过可预测的 pause time 模型控制停顿&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;初始标记(STW) → 并发标记 → 最终标记(STW) → 筛选回收(STW)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;初始标记&lt;/strong&gt;：标记 GC Roots + 修改 TAMS（Next Top at Mark Start）指针&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;并发标记&lt;/strong&gt;：从 GC Roots 遍历所有对象，记录引用变更到 SATB（Snapshot At The Beginning）队列&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;最终标记&lt;/strong&gt;：处理 SATB 队列中的漏标对象&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;筛选回收&lt;/strong&gt;：计算每个 Region 的回收价值（回收能释放多少空间 × 回收耗时），优先回收&amp;quot;垃圾最多、回收最快&amp;quot;的 Region&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;关键内部机制&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&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;&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;strong&gt;Region&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;堆划分为 1MB~32MB 的 Region，每个 Region 可扮演 Eden/Survivor/Old/Humongous&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;strong&gt;RSet（Remembered Set）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;记录其他 Region 对本 Region 的引用——避免全堆扫描&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;strong&gt;SATB（Snapshot At The Beginning）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;并发标记开始时拍堆快照，所有在标记期间变更的引用都记录到 SATB 队列&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;strong&gt;写屏障&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;对象引用变更时触发，更新 RSet + 记录 SATB&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：堆大小 4GB+，多核 CPU，延迟要求 100-300ms&lt;/p&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;-XX:+UseG1GC&lt;/code&gt;：启用（JDK 9+ 默认）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt;：期望暂停时间目标（默认 200ms，G1 会努力但无法硬保证）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1HeapRegionSize&lt;/code&gt;：Region 大小（默认堆/2048，1~32MB）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:InitiatingHeapOccupancyPercent&lt;/code&gt;：触发并发标记的堆使用率（默认 45%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1NewSizePercent&lt;/code&gt;：新生代最小占比（默认 5%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1MaxNewSizePercent&lt;/code&gt;：新生代最大占比（默认 60%）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;何时选 G1&lt;/strong&gt;：JDK 11+、堆 4GB+、延迟要求几百毫秒，G1 是默认选择。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;5-zgcz-garbage-collector&#34;&gt;5. ZGC（Z Garbage Collector）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：极低延迟（STW &amp;lt; 10ms），与堆大小基本无关（即使是 TB 级堆）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么能这么低延迟&lt;/strong&gt;：几乎所有阶段都并发，只在极少数点 STW（且 STW 阶段不随堆大小增长）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;关键技术&lt;/strong&gt;：&lt;/li&gt;&#xA;&lt;/ul&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;&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;strong&gt;染色指针（Colored Pointers）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;在 64 位指针的高位（42 位之后）存储 GC 状态信息（Finalizable/Remapped/Mark1/Mark0），无需额外内存&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;strong&gt;读屏障（Load Barrier）&lt;/strong&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;strong&gt;并发迁移（Relocation）&lt;/strong&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;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发标记（Concurrent Mark）&lt;/strong&gt;：遍历对象图，标记存活对象。与 G1 不同，ZGC 的标记完全并发（初始标记的 STW 极短）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发迁移预备（Concurrent Prepare for Relocation）&lt;/strong&gt;：确定需要清理的 Region。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发迁移（Concurrent Relocate）&lt;/strong&gt;：将存活对象复制到新 Region，更新引用。读屏障确保应用线程始终访问到正确地址。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发重映射（Concurrent Remap）&lt;/strong&gt;：修正所有指向旧位置的引用。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：TB 级堆、延迟要求 &amp;lt; 10ms 的金融交易/实时系统&lt;/p&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;-XX:+UseZGC&lt;/code&gt;：启用（JDK 11 实验性，JDK 15 正式，JDK 18+ 默认）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ZAllocationSpikeTolerance&lt;/code&gt;：分配尖峰容忍度（默认 2.0）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ZCollectionInterval&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;：ZGC 的吞吐量略低于 G1（因为读屏障开销），内存占用也更高。选 ZGC 时确认你能接受这些 Trade-off。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;6-shenandoah-gc&#34;&gt;6. Shenandoah GC&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：与 ZGC 类似，目标是极低延迟。与 ZGC 的区别在于实现方式：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ZGC 使用染色指针（需要 64 位系统 + 特定 CPU 特性）&lt;/li&gt;&#xA;&lt;li&gt;Shenandoah 使用 Brooks 指针（对象头中加一个转发指针），不依赖硬件&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：并发标记 → 并发转移 → 并发更新引用（比 ZGC 多一个并发更新引用阶段）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：与 ZGC 类似，但不要求特定硬件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseShenandoahGC&lt;/code&gt;：启用（JDK 12+，OpenJDK 发行版不默认包含——需要 Build 时开启）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ShenandoahGCHeuristics&lt;/code&gt;：启发式策略（adaptive/static/compact/aggressive）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;三gc-选择决策树&#34;&gt;三、GC 选择决策树&#xA;&lt;/h2&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;应用需要什么？&#xA;├─ 批处理/数据分析 → Parallel（要吞吐量）&#xA;├─ Web 服务/微服务&#xA;│  ├─ 堆 &amp;lt; 4GB → G1 或 Parallel&#xA;│  ├─ 堆 4~16GB → G1（JDK 11+ 默认）&#xA;│  ├─ 堆 &amp;gt; 16GB + 延迟敏感 → G1（延迟要求 &amp;lt; 100ms？）&#xA;│  │  └─ 是 → ZGC（JDK 17+）&#xA;│  └─ 堆 &amp;gt; 100GB + 极致低延迟 → ZGC&#xA;└─ 客户端/小型应用 → Serial&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;四gc-优化实践&#34;&gt;四、GC 优化实践&#xA;&lt;/h2&gt;&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;li&gt;&lt;strong&gt;收集数据&lt;/strong&gt;：PrintGCDetails + GCViewer/GCEasy 分析 GC 日志&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;常用-jvm-参数组合&#34;&gt;常用 JVM 参数组合&#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;# 打印 GC 日志（JDK 9+）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-Xlog:gc*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-Xlog:gc:gc.log&#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;# 打印 GC 日志（JDK 8）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log&#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;# G1 生产环境常用参数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+UseG1GC -XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; -XX:+PrintGCDetails&#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;# 大堆 ZGC 常用参数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+UseZGC -Xms64G -Xmx64G -XX:ZAllocationSpikeTolerance&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;2.0&#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;ol&gt;&#xA;&lt;li&gt;Heap Dump + MAT（Memory Analyzer Tool）分析大对象&lt;/li&gt;&#xA;&lt;li&gt;GC 日志中 &lt;code&gt;Full GC&lt;/code&gt; 频率异常 → 确认是否为晋升失败或 MetaSpace 泄漏&lt;/li&gt;&#xA;&lt;li&gt;Native Memory Tracking（NMT）检查 off-heap 内存&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五跨代引用与-rset-详解&#34;&gt;五、跨代引用与 RSet 详解&#xA;&lt;/h2&gt;&lt;h3 id=&#34;g1-的-rsetremembered-set&#34;&gt;G1 的 RSet（Remembered Set）&#xA;&lt;/h3&gt;&lt;p&gt;每个 Region 维护一个 RSet，记录其他 Region 对它的引用。为什么需要 RSet？Young GC 时只扫描新生代 Region，但老年代可能有对象引用新生代对象——有了 RSet 就不必全堆扫描。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;RSet 的结构&lt;/strong&gt;：哈希表，key 是来源 Region 地址，value 是来源 Region 中的卡页索引（Card Index）。卡页默认 512 字节。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;写屏障维护 RSet&lt;/strong&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;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writeBarrier&lt;/span&gt;(Field field, Object newObj) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Object oldObj &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; field.&lt;span style=&#34;color:#a6e22e&#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:#66d9ef&#34;&gt;if&lt;/span&gt; (oldObj &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; isCrossRegionRef(oldObj, newObj)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        addToRSet(oldObj.&lt;span style=&#34;color:#a6e22e&#34;&gt;region&lt;/span&gt;(), newObj.&lt;span style=&#34;color:#a6e22e&#34;&gt;region&lt;/span&gt;(), getCardIndex(oldObj));&#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;    field.&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(newObj);&#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;g1-vs-cms-跨代引用处理对比&#34;&gt;G1 vs CMS 跨代引用处理对比&#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;G1&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;CMS&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;每个 Region 维护 RSet&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;全局卡表（Card Table）&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;精确到 Region + 卡页&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;较高（每个 Region 一个 RSet）&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;仅扫描相关 Region&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>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>ElasticSearch 知识</title>
            <link>https://xumf.net/blog/elasticsearch/</link>
            <pubDate>Sun, 22 Apr 2018 13:16:53 +0800</pubDate>
            <guid>https://xumf.net/blog/elasticsearch/</guid>
            <description>&lt;h2 id=&#34;1-elasticsearch-概念与架构&#34;&gt;1. Elasticsearch 概念与架构&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;集群(Cluster)&lt;/strong&gt;：Elasticsearch 中的多个节点(Node)组成集群。一个集群中有一个主节点(Master Node)，负责集群管理，其它节点可能是数据节点(Data Node)、协调节点(Coordinating Node)、以及 Ingest 节点等。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;节点(Node)&lt;/strong&gt;：每个 Elasticsearch 实例都被称为节点，节点存储数据并处理请求。节点可以有不同角色，如&lt;code&gt;master&lt;/code&gt; 、&lt;code&gt;data&lt;/code&gt; 、&lt;code&gt;ingest&lt;/code&gt; 等。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;索引(Index)&lt;/strong&gt;：Elasticsearch 中数据的存储单位，每个索引包含多个分片(Shards)，可以进行高效的存储与查询。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;分片(Shard)&lt;/strong&gt;：每个索引会被分割成多个分片，分片是数据存储的基本单位，主分片和副本分片提供了数据的分布与冗余&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;2--核心原理&#34;&gt;2.  核心原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;11-倒排索引inverted-index&#34;&gt;1.1 倒排索引(Inverted Index)&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;原理&lt;/strong&gt;：通过词项(&lt;strong&gt;Term&lt;/strong&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;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;与正排索引对比&lt;/strong&gt;：正排索引通过文档 ID 查找内容，倒排索引通过词项找文档&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;12-分布式架构&#34;&gt;1.2 分布式架构&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;分片(Shard)：&lt;/em&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;主分片(Primary)&lt;/strong&gt;*：*处理写操作，数量创建索引时固定&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;副本分片(Replica)&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;Master 节点&lt;/strong&gt;：管理集群状态(如索引创建、节点上下线)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Data 节点&lt;/strong&gt;：存储分片，处理数据 CURD&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Coordinating 节点&lt;/strong&gt;：路由请求，聚合结果(默认所有节点均可担任)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ingest 节点&lt;/strong&gt;：&#xA;&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;：通过定义 &lt;strong&gt;Pipeline&lt;/strong&gt;(处理管道)，对原始数据进行加工，例如：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;解析结构&lt;/strong&gt;：如将日志中的非结构化文本解析为结构化字段(使用&lt;code&gt;Grok&lt;/code&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;：如添加地理位置信息、基于 IP 生成 GeoIP 字段。&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;/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;：将计算密集型的预处理任务从 Data 节点剥离，避免影响索引和查询功能。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;资源优化&lt;/strong&gt;：专用 Ingest 节点可配置更高 CPU 资源，专注于数据处理。&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;替代部分 Logstash 功能&lt;/strong&gt;：在不需要复杂 ETL 的场景中，可直接通过 Elasticsearch 完成数据处理，减少外部组件依赖。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;13-近实时nrtnear-real-time&#34;&gt;1.3 近实时(NRT，Near Real-Time)&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Refresh 机制&lt;/strong&gt;：内存缓冲区数据每隔一秒(默认)生成新 Segment(文件系统缓存)，实现可搜索&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Translog 持久化&lt;/strong&gt;：写入操作记录到事务日志，定期 Flush 到磁盘保证数据安全&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;14-查询流程&#34;&gt;1.4 查询流程&#xA;&lt;/h3&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;：根据需求，客户端可能发起 Get 请求(通过 ID 获取文档)或 &lt;strong&gt;Search&lt;/strong&gt; 请求(复杂查询)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;目标节点&lt;/strong&gt;：客户端将请求发送到集群中的任意节点，该节点默认担任&lt;strong&gt;协调节点(Coordinating Node&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;Get by ID&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;协调节点通过&lt;strong&gt;路由算法&lt;/strong&gt;(如&lt;code&gt;hash(_id) % number_of_shards&lt;/code&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;Search 请求&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;若查询未指定路由，协调节点将请求广播到索引的&lt;strong&gt;所有分片&lt;/strong&gt;(主分片或副本分片)&lt;/li&gt;&#xA;&lt;li&gt;若指定路由参数，仅查询关联的分片&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;分片本地查询(Query Phase)&lt;/strong&gt;&#xA;&lt;ul&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;li&gt;对于搜索请求，分片返回&lt;strong&gt;匹配文档的 ID 和排序值&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;Top N 结果&lt;/strong&gt;(N 有&lt;code&gt;size&lt;/code&gt; 参数决定)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;全局结果合并(Coordinating Node)&lt;/strong&gt;&#xA;&lt;ul&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;筛选最终** Top N 文档的 ID 列表 **(例如用户请求的 &lt;code&gt;size=10&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;code&gt;from + size&lt;/code&gt; ，协调节点需要合并所有分片的&lt;code&gt;from + size&lt;/code&gt; 条数据，内存开销大。推荐使用 &lt;strong&gt;Search After&lt;/strong&gt; 或 &lt;strong&gt;Scroll API&lt;/strong&gt; 替代&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;获取文档详情(Fetch Phase)&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;二次请求&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;协调节点根据筛选后的文档 ID，向对应分片发送 &lt;strong&gt;Multi-Get 请求&lt;/strong&gt;获取完整文档内容&lt;/li&gt;&#xA;&lt;li&gt;分片返回文档的原始数据(如&lt;code&gt;_source&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;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;搜索请求&lt;/strong&gt;：依赖 &lt;strong&gt;Refresh 机制&lt;/strong&gt;(默认1秒生成新 Segment)，未刷新前不可被搜索&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Get 请求&lt;/strong&gt;：通过实施读取 &lt;strong&gt;Translog&lt;/strong&gt; 可立即获取最新文档，无需等待 Refresh&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;：&#xA;&lt;ul&gt;&#xA;&lt;li&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;/li&gt;&#xA;&lt;/ul&gt;&#xA;&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;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;缓存聚合结果或频繁查询的响应(仅对不含&lt;code&gt;now&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;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;15-写入流程&#34;&gt;1.5 写入流程&#xA;&lt;/h3&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;：可以是单文档写入(&lt;code&gt;PUT /index/_doc/1&lt;/code&gt; )、批量写入(&lt;code&gt;Bulk API&lt;/code&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;路由规则&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;若指定文档 ID，使用哈希算法：&lt;code&gt;hash(_id) % number_of_shards&lt;/code&gt; 确定目标分片&lt;/li&gt;&#xA;&lt;li&gt;若未指定 ID(自动生成 ID)，Elasticsearch 会随机选择主分片&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;分片定位&lt;/strong&gt;：协调节点根据路由结果，将请求转发到该主分片所在的** Data 节点**&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;主分片写入处理&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;3.1 写入内存缓冲去&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存缓冲区(Index Buffer)&lt;/strong&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;（尚未生成 Segment）&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;对文档字段进行分词（根据 mapping 定义的分词器）&lt;/li&gt;&#xA;&lt;li&gt;生成倒排序索引的临时数据结构&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;3.2 写入 Translog (事务日志)&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Translog 作用&lt;/strong&gt;：确保数据未持久化到磁盘前不会丢失&#xA;&lt;ul&gt;&#xA;&lt;li&gt;所有写入操作会&lt;strong&gt;同步追加&lt;/strong&gt;到 Translog&lt;/li&gt;&#xA;&lt;li&gt;Translog 默认每次请求后刷新(&lt;code&gt;index.translog.durability: request&lt;/code&gt; )，保证可靠性&lt;/li&gt;&#xA;&lt;li&gt;可配置为异步刷新(&lt;code&gt;async&lt;/code&gt;)以提高性能，但可能丢失部分数据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;3.3 副本分片同步(Replication)&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&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;strong&gt;副本分片&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;副本分片执行相同的写入流程(写入内存缓冲区 + Translog)&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;code&gt;wait_for_active_shards: quorum&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;若副本分片写入失败，主分片会重试，最终可能标记副本分片为失效&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;返回客户端响应&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;成功条件&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;主分片和副本分片均为完成内存和 Translog 写入后，协调节点向客户端返回&lt;code&gt;acknowledged: true&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;code&gt;yellow&lt;/code&gt; (副本未分配)&lt;/li&gt;&#xA;&lt;li&gt;客户端可能收到&lt;code&gt;ShardFailureException&lt;/code&gt; (需重试或处理异常)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;5&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;近实时搜索实现(Refresh)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Refresh机制&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;默认每个&lt;strong&gt;1秒&lt;/strong&gt;(&lt;code&gt;index.refresh_interval&lt;/code&gt; )，内存缓冲区的数据会生成新的 &lt;strong&gt;Lucene Segment&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;Segment 写入&lt;strong&gt;文件系统缓存&lt;/strong&gt;(非磁盘)，此时数据可被搜索&lt;/li&gt;&#xA;&lt;li&gt;Refresh 操作开销较大，高频写入场景可适当调大间隔(如30秒)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;6&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;数据持久化(Flush)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Flush 触发条件&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Translog 大小达到阈值(默认512MB，&lt;code&gt;index.translog.flush_threshold_size&lt;/code&gt; )&lt;/li&gt;&#xA;&lt;li&gt;时间间隔(默认30分钟，&lt;code&gt;index.translog.sync_interval&lt;/code&gt; )&lt;/li&gt;&#xA;&lt;li&gt;手动调用&lt;code&gt;_flush&lt;/code&gt; API&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;清空内存缓冲区，将所有 Segment 持久化到磁盘&lt;/li&gt;&#xA;&lt;li&gt;清空当前 Translog，生成新的 Translog 文件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Segment 只读&lt;/strong&gt;：写入磁盘后不再修改，删除操作通过&lt;code&gt;.del&lt;/code&gt; 文件标记&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;7&#34;&gt;&#xA;&lt;li&gt;Segment 合并(Merge)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;后台优化&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;多个 Segment 会被合并为更大的 Segment，提升查询性能&lt;/li&gt;&#xA;&lt;li&gt;合并过程自动触发，删除过期文档(如标记为删除的文档)&lt;/li&gt;&#xA;&lt;li&gt;合并期间可能占用较多I/O和 CPU 资源&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;8&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;容错与恢复机制&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;节点宕机恢复&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;重启后，通过重放 Translog 恢复未持久化的数据&lt;/li&gt;&#xA;&lt;li&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;code&gt;_seq_no&lt;/code&gt; 和&lt;code&gt;_primary_term&lt;/code&gt; 保证写入顺序和冲突解决&lt;/li&gt;&#xA;&lt;li&gt;写入时可通过&lt;code&gt;version&lt;/code&gt; 参数实现乐观锁控制&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;3--倒排索引的底层实现&#34;&gt;3.  倒排索引的底层实现&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;3.1 核心数据结构&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;词典(Term Dictionary)&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用** FST(有限状态转换机)** 压缩存储词项，减少内存占用(Lucene 6.0 后默认)。&lt;/li&gt;&#xA;&lt;li&gt;支持快速前缀查询(如通配符&lt;code&gt;*&lt;/code&gt;)，但需权衡内存与查询性能。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;倒排列表(Postings List)&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;DocID 列表&lt;/strong&gt;：使用差值编码(Delta Encoding)和 **Frame Of Reference(FOR)**压缩。&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-Plain&#34; data-lang=&#34;Plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;原始ID：100, 200, 300 → 差值：100, 100, 100 → 压缩为单值100 + 重复次数。&#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;词频(TF)与位置(Position)&lt;/strong&gt;：使用**位压缩(Bit Packing)和游程编码(RLE)**。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;3.2 倒排索引的局限性&lt;/strong&gt;&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;code&gt;doc_values&lt;/code&gt; 优化)。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;4-分布式设计的深度剖析&#34;&gt;4. 分布式设计的深度剖析&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;4.1 分片策略的权衡&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&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;li&gt;&lt;strong&gt;过多&lt;/strong&gt;：元数据管理开销大(每个分片是独立 Lucence 索引)，查询合并成本高。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;黄金法则&lt;/strong&gt;：单个分片大小建议在** 10-50GB **，结合数据增长速率设计。&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;code&gt;routing&lt;/code&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-Plain&#34; data-lang=&#34;Plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PUT /logs/_doc/1?routing=node-1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ &amp;#34;message&amp;#34;: &amp;#34;error in node-1&amp;#34; }&#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;弊端&lt;/strong&gt;：可能导致数据倾斜(如某个路由值数据量过大)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;4.2 分布式一致性模型&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&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;code&gt;wait_for_active_shards&lt;/code&gt; (默认为&lt;code&gt;quorum&lt;/code&gt; ，即&lt;code&gt;(主分片数+副本数)/ 2 + 1)&lt;/code&gt; 。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;场景&lt;/strong&gt;：若副本分片故障，主分片写入成功后仍返回成功，但集群状态为&lt;code&gt;yellow&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;li&gt;&lt;strong&gt;强制读主分片&lt;/strong&gt;：设置&lt;code&gt;preference=_primary&lt;/code&gt; ，但牺牲性能。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;4.3 脑裂问题与防范&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;原因&lt;/strong&gt;：网络分区导致多个 Master 节点被选举。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;discovery.zen.minimun_master_nodes&lt;/code&gt; (ES 7.x前)：设置为&lt;code&gt;(master 节点数 / 2)+ 1&lt;/code&gt; 。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;5-查询流程深度优化&#34;&gt;5. 查询流程深度优化&#xA;&lt;/h2&gt;&lt;p&gt;5.1 &lt;strong&gt;Query 与 Filter 的执行差异&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Query 上下文&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;计算相关性评分(&lt;code&gt;score&lt;/code&gt;)，无法缓存，适合全文搜索&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;代价&lt;/strong&gt;：频繁访问到排序索引，CPU 消耗高。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Filter 上下文&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;仅判断是否匹配，结果可缓存(使用&lt;code&gt;bitset&lt;/code&gt;)，适合精准过滤。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;优化技巧&lt;/strong&gt;：将范围查询、&lt;code&gt;term&lt;/code&gt; 查询至于&lt;code&gt;filter&lt;/code&gt; 中。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;5.2 &lt;strong&gt;聚合(Aggregation)的底层实现&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;全局排序限制&lt;/strong&gt;:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;terms&lt;/code&gt; 聚合默认返回每个分片的 Top 结果再合并，可能导致精度损失。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：设置&lt;code&gt;size: 10000&lt;/code&gt; + &lt;code&gt;shard_size: 50000&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;code&gt;fielddata&lt;/code&gt; 使用(避免&lt;code&gt;CircuitBreaker&lt;/code&gt; 触发)。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;5.3 &lt;strong&gt;查询性能优化&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;索引设计&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用&lt;code&gt;keyword&lt;/code&gt; 类型替代&lt;code&gt;text&lt;/code&gt; ，避免分词开销。&lt;/li&gt;&#xA;&lt;li&gt;禁用&lt;code&gt;_all&lt;/code&gt; 字段(ES 6.0+默认禁用，替换为&lt;code&gt;copy_to&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;code&gt;term&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;strong&gt;Search After&lt;/strong&gt;：利用上一页的排序值(如&lt;code&gt;@timestamp&lt;/code&gt; )避免深分页。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Scroll API&lt;/strong&gt;：创建快照上下文，适合离线导出(但消耗资源)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;6-高级调优参数&#34;&gt;6. 高级调优参数&#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;strong&gt;参数&lt;/strong&gt;&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;&lt;strong&gt;作用&lt;/strong&gt;&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;&lt;strong&gt;推荐值&lt;/strong&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;strong&gt;indices.memory.index_buffer_size&lt;/strong&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;10%(默认)&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;strong&gt;index.refresh_interval&lt;/strong&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;30s&lt;/code&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;strong&gt;index.translog.flush_threshold_size&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;Translog刷盘阈值&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;code&gt;1gb&lt;/code&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;strong&gt;index.merge.scheduler.max_thread_count&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;合并线程数(需 SSD 支持)&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;code&gt;4&lt;/code&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;strong&gt;search.max_buckets&lt;/strong&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;100000&lt;/code&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;6-架构运行相关流程图&#34;&gt;6. 架构运行相关流程图&#xA;&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;images/10ae25fa-00a2-4642-a1ce-f58cfdad9224.svg&#34; &gt;drawio&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;快速问答&#34;&gt;快速问答&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Translog 如何保证数据安全？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Translog 使用追加写入(Append-Only)模式，避免随机写磁盘的性能问题&lt;/li&gt;&#xA;&lt;li&gt;通过 fsync 系统调度强制刷盘(依赖&lt;code&gt;index.translog.durability&lt;/code&gt; 配置)&lt;/li&gt;&#xA;&lt;li&gt;崩溃恢复：节点重启时，通过 Translog 重放未持久化到 Lucene Segment 的操作&lt;/li&gt;&#xA;&lt;li&gt;源码关联：&lt;code&gt;org.elasticsearch.index.translog.Translog&lt;/code&gt; 类处理日志的写入与恢复&lt;/li&gt;&#xA;&lt;li&gt;与 Lucene Commit 的关系：Flush 操作会将内存数据生成 Segment 并刷盘，同时清除已提交的 Translog&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;使用 Bulk API、调大 Refresh 间隔&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;实战案例：在日志系统中，将&lt;code&gt;refresh_interval&lt;/code&gt; 设为&lt;code&gt;30s&lt;/code&gt; ，写入吞吐量提升 3 倍，但需接受搜索延迟&lt;/li&gt;&#xA;&lt;li&gt;参数调优：调整&lt;code&gt;indices.memory.index_buffer_size&lt;/code&gt; (默认 10% 堆内存)增加索引缓冲区&lt;/li&gt;&#xA;&lt;li&gt;硬件影响：使用 SSD 减少 Flush 耗时，避免写入瓶颈&lt;/li&gt;&#xA;&lt;li&gt;监控工具：通过 Kibana Monitoring 观察&lt;code&gt;indexing_rate&lt;/code&gt;和&lt;code&gt;merge_time&lt;/code&gt; ，针对性优化&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Elasticsearch 和关系型数据库的写入区别&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;数据模型：ES 时 Schema-less 的文档模型，支持动态字段；关系数据库需预定义 Schema&lt;/li&gt;&#xA;&lt;li&gt;事务性：ES 不支持 ACID 事务，依赖版本号(&lt;code&gt;_version&lt;/code&gt; )实现乐观锁&lt;/li&gt;&#xA;&lt;li&gt;写入延迟：ES 的 NRT(近实时)vs 数据库的实时可见&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Refresh 机制对写入性能的影响&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Refresh 操作将内存缓冲区中的数据生成新的 Lucene Segment，写入文件系统缓存(非磁盘)，使数据可被搜索)&lt;/li&gt;&#xA;&lt;li&gt;频繁 Refresh 会导致产生大量小 Segment，增加 Merge 开销(I/O 和 CPU 竞争)&lt;/li&gt;&#xA;&lt;li&gt;日志数据：设置&lt;code&gt;refresh_interval: 30s&lt;/code&gt; 甚至&lt;code&gt;-1&lt;/code&gt; (关闭自动 Refresh)，通过手动 Refresh 控制搜索可见性&lt;/li&gt;&#xA;&lt;li&gt;高查询压力：避免长时间不 Refresh，否则新数据无法被搜索&lt;/li&gt;&#xA;&lt;li&gt;监控指标：通过&lt;code&gt;_nodes/states/indices/&lt;/code&gt; API 观察&lt;code&gt;refresh_tatol&lt;/code&gt; 和&lt;code&gt;refresh_time_in_millis&lt;/code&gt; ，评估 Refresh 开销&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;副本分片写入成功后，主分片才向客户端返回确认&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;wait_for_active_shards: quorm&lt;/code&gt; (默认)：多数分片(主 + 副本)可用时写入成功&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;wati_for_active_shards: 1&lt;/code&gt; ：仅主分片成功即可(风险：副本可能落后)&lt;/li&gt;&#xA;&lt;li&gt;若副本分片写入失败，主分片会向 Master 节点报告，触发分片重分配&lt;/li&gt;&#xA;&lt;li&gt;集群状态变为&lt;code&gt;Yellow&lt;/code&gt; ，直到副本恢复&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;设计一个支持亿级日志写入的系统，你会如何规划 ES 集群？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;分片设计：按时间滚动索引(如&lt;code&gt;logs-2023-10&lt;/code&gt; )，单个分片大小控制在 50GB 以内&lt;/li&gt;&#xA;&lt;li&gt;写入优化：使用 Bulk API，客户端侧实现批量压缩与重试机制&lt;/li&gt;&#xA;&lt;li&gt;硬件规划：独立 Ingest 节点处理数据预处理，Data 节点使用 NVMe SSD&lt;/li&gt;&#xA;&lt;li&gt;可靠性：设置&lt;code&gt;index.translog.durability: async&lt;/code&gt; ，副本数设为 1&lt;/li&gt;&#xA;&lt;li&gt;监控：通过 ILM(索引生命周期管理)自动归档旧索引到冷存储&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么 Elasticsearch 查询比数据库快？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;倒排序索引：快速定位文档，避免全表扫描。&lt;/li&gt;&#xA;&lt;li&gt;分布式并行：查询拆分到多个分片并行执行。&lt;/li&gt;&#xA;&lt;li&gt;文件系统缓存：Segment 文件缓存在 OS Cache，减少磁盘 IO。&lt;/li&gt;&#xA;&lt;li&gt;列式存储(&lt;code&gt;doc_values&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;code&gt;wait_for_active_shards&lt;/code&gt; 控制最小成功分片数。&lt;/li&gt;&#xA;&lt;li&gt;版本控制：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;使用&lt;code&gt;_version&lt;/code&gt; 实现乐观锁，避免并发覆盖。&lt;/li&gt;&#xA;&lt;li&gt;外部版本号(&lt;code&gt;version_type=external&lt;/code&gt; )兼容数据库同步。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;读一致性：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;preference=_primary&lt;/code&gt; ：强制读主分片(强一致性，性能低)。&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;replication=async&lt;/code&gt; ：异步副本更新(最终一致性，性能高)。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;如何设计一个高可用 ES 集群？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;节点角色分离：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;专用 Master 节点（3台，避免脑裂）。&lt;/li&gt;&#xA;&lt;li&gt;独立 Data 节点、Ingest 节点、Coordination 节点。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;分片策略：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;副本数≥1，跨机架分布（&lt;code&gt;awareness&lt;/code&gt; 参数）。&lt;/li&gt;&#xA;&lt;li&gt;使用ILM（索引生命周期管理）自动滚动索引。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;容灾备份：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;快照（Snapshot）到 S3/NFS，支持跨集群恢复。&lt;/li&gt;&#xA;&lt;li&gt;多集群同步（CCR，跨集群复制）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</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>
