<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>故障排查 on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5/</link>
        <description>Recent content in 故障排查 on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Sat, 11 Jul 2026 07:00:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>一次服务本地端口耗尽导致对外调用大量 Cannot assign requested address 的排查记录</title>
            <link>https://blog.5772447.xyz/posts/1925cf22/</link>
            <pubDate>Sat, 11 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/1925cf22/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们有一个订单聚合服务（Go 编写，跑在 8 核 16G 的云主机上），它的职责是接收前端下单请求后，再去调用下游的库存、优惠券、风控三个内部 HTTP 接口，把结果聚合返回。日常 QPS 在 3000 左右，一直很稳。&lt;/p&gt;&#xA;&lt;p&gt;某天上午做了一次营销活动，流量涨到平时的 3~4 倍。活动开始约 20 分钟后，监控告警开始刷屏：订单服务的下游调用成功率从 99.9% 掉到 70% 以下，前端下单大面积超时。奇怪的是，被调用的库存、优惠券、风控三个服务自身指标都正常，CPU、内存、响应时间没有任何异常——问题明显出在&amp;quot;调用方&amp;quot;这一侧。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;登录订单服务所在主机，第一时间看应用日志，发现海量报错，几乎每秒都在刷：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dial tcp 10.20.3.11:8080: connect: cannot assign requested address&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dial tcp 10.20.3.12:8080: connect: cannot assign requested address&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dial tcp 10.20.3.13:8080: connect: cannot assign requested address&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;三个下游 IP 全部中招，且都是同一个报错：&lt;code&gt;cannot assign requested address&lt;/code&gt;。这个报错对应的 errno 是 &lt;code&gt;EADDRNOTAVAIL&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;的：有时候一批请求全部成功，紧接着一批又全部失败，呈现&amp;quot;一阵一阵&amp;quot;的规律。&lt;/li&gt;&#xA;&lt;li&gt;服务自身的 CPU 只有 40% 左右，内存充足，GC 正常，&lt;strong&gt;完全不是资源打满&lt;/strong&gt;的样子。&lt;/li&gt;&#xA;&lt;li&gt;下游服务端全程健康，网络到下游的 ping/traceroute 也没有丢包和延迟抖动。&lt;/li&gt;&#xA;&lt;li&gt;重启订单服务后，报错会消失几分钟，然后卷土重来。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;code&gt;cannot assign requested address&lt;/code&gt; 这个错误很有指向性：它不是&amp;quot;连不上对端&amp;quot;（那是 &lt;code&gt;connection refused&lt;/code&gt; 或 &lt;code&gt;timeout&lt;/code&gt;），而是&lt;strong&gt;本机在发起连接、准备分配一个本地端口时就失败了&lt;/strong&gt;。也就是说，本机的可用源端口（ephemeral port）不够用了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;第一步确认端口占用情况&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e7%a1%ae%e8%ae%a4%e7%ab%af%e5%8f%a3%e5%8d%a0%e7%94%a8%e6%83%85%e5%86%b5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一步：确认端口占用情况&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;TCP 主动发起连接时，内核会从本地临时端口范围里挑一个空闲端口作为源端口。先看这个范围：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ cat /proc/sys/net/ipv4/ip_local_port_range&#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;32768&lt;/span&gt;   &lt;span style=&#34;color:#ae81ff&#34;&gt;60999&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;也就是可用临时端口约 &lt;code&gt;60999 - 32768 = 28231&lt;/code&gt; 个。看起来不算少，但在高并发短连接场景下并不够。&lt;/p&gt;&#xA;&lt;p&gt;再统计当前 TCP 连接状态分布：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ ss -ant | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt; | sort | uniq -c | sort -rn&#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;26841&lt;/span&gt; TIME-WAIT&#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;2013&lt;/span&gt; ESTAB&#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;47&lt;/span&gt; LISTEN&#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;12&lt;/span&gt; SYN-SENT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;问题一下就清晰了：&lt;strong&gt;TIME-WAIT 高达 2.6 万条&lt;/strong&gt;，几乎把 28231 个临时端口范围占满了。剩下能分配的端口寥寥无几，内核挑不到空闲端口，就直接返回 &lt;code&gt;EADDRNOTAVAIL&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步搞清楚-time_wait-是谁产生的&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e6%90%9e%e6%b8%85%e6%a5%9a-time_wait-%e6%98%af%e8%b0%81%e4%ba%a7%e7%94%9f%e7%9a%84&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二步：搞清楚 TIME_WAIT 是谁产生的&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;进一步看这些 TIME_WAIT 连的是谁：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ ss -ant state time-wait | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $4}&amp;#39;&lt;/span&gt; | sed &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;s/:[0-9]*$//&amp;#39;&lt;/span&gt; | sort | uniq -c | sort -rn&#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;9021&lt;/span&gt; 10.20.3.11&#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;8890&lt;/span&gt; 10.20.3.12&#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;8720&lt;/span&gt; 10.20.3.13&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;全部指向三个下游服务的 IP。也就是说，是&lt;strong&gt;订单服务作为客户端，主动关闭了与下游的连接&lt;/strong&gt;，从而在本机堆积了大量 TIME_WAIT（TIME_WAIT 始终出现在主动关闭连接的一方）。&lt;/p&gt;&#xA;&lt;p&gt;为什么会有这么多短连接？拉出这个服务调用下游的 HTTP 客户端代码看，发现问题所在：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 有问题的写法：每次调用都新建 client&lt;/span&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;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;callInventory&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;req&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Req&lt;/span&gt;) (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Resp&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&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;client&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Client&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&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;resp&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;client&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Post&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;body&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&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;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;每次请求都 &lt;code&gt;new&lt;/code&gt; 一个 &lt;code&gt;http.Client&lt;/code&gt;，用完即弃。Go 的连接复用（keep-alive）依赖于&lt;strong&gt;复用同一个 Transport/Client&lt;/strong&gt;；每次新建 Client 会创建全新的 Transport，请求结束后连接无法进入连接池被复用，直接被关闭，于是每一次下游调用都变成一条&amp;quot;建连—请求—主动关闭&amp;quot;的短连接。&lt;/p&gt;&#xA;&lt;p&gt;流量放大 3~4 倍后，短连接产生速率超过了 TIME_WAIT 的回收速率（默认 &lt;code&gt;2*MSL = 60s&lt;/code&gt;），端口于是被迅速耗尽。这也解释了为什么报错是&amp;quot;一阵一阵&amp;quot;的：端口耗尽 → 报错 → 部分 TIME_WAIT 到期释放 → 又能分配一批 → 再次耗尽。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步排除内核参数误配&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e6%ad%a5%e6%8e%92%e9%99%a4%e5%86%85%e6%a0%b8%e5%8f%82%e6%95%b0%e8%af%af%e9%85%8d&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三步：排除内核参数误配&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;顺手确认了两个常被误用的内核参数：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ sysctl net.ipv4.tcp_tw_reuse&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_reuse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sysctl net.ipv4.tcp_tw_recycle&#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;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;tcp_tw_recycle&lt;/code&gt; 在 NAT 环境下会导致丢包，早已在 4.12 内核被删除，不能用。&lt;code&gt;tcp_tw_reuse&lt;/code&gt; 是安全的，允许在协议安全的前提下复用处于 TIME_WAIT 的端口给&lt;strong&gt;新的对外连接&lt;/strong&gt;使用，但当时是关闭状态。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;分两步走：先止血，再根治。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;1. 紧急止血（内核层面，无需改代码即可缓解）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 允许复用 TIME_WAIT 端口用于新的对外连接（客户端安全）&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_tw_reuse&lt;span style=&#34;color:#f92672&#34;&gt;=&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:#75715e&#34;&gt;# 适当扩大临时端口范围&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.ip_local_port_range&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10000 65535&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;改完后端口从约 2.8 万可用扩到约 5.5 万，加上 &lt;code&gt;tw_reuse&lt;/code&gt; 复用，报错率立刻从 30% 降到 2% 以下，先把活动扛过去。写入 &lt;code&gt;/etc/sysctl.conf&lt;/code&gt; 持久化：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.tcp_tw_reuse = 1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;net.ipv4.ip_local_port_range = 10000 65535&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2. 根治（应用层面，复用连接）&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;真正的病根是短连接。把 HTTP 客户端改成全局单例并配置好连接池：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;httpClient&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Client&lt;/span&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;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&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;Transport&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Transport&lt;/span&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;MaxIdleConns&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;        &lt;span style=&#34;color:#a6e22e&#34;&gt;MaxIdleConnsPerHost&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#75715e&#34;&gt;// 关键：默认只有 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:#a6e22e&#34;&gt;IdleConnTimeout&lt;/span&gt;:     &lt;span style=&#34;color:#ae81ff&#34;&gt;90&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;重点是 &lt;code&gt;MaxIdleConnsPerHost&lt;/code&gt;：Go 默认每个 host 只保留 2 个空闲连接，超出的连接用完即关，同样会退化成短连接。调大后，与每个下游之间维持一个稳定的长连接池，请求走 keep-alive 复用，几乎不再新建/关闭连接。&lt;/p&gt;&#xA;&lt;p&gt;改造上线后再看：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ ss -ant | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $1}&amp;#39;&lt;/span&gt; | sort | uniq -c | sort -rn&#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;1980&lt;/span&gt; ESTAB&#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;210&lt;/span&gt; TIME-WAIT&#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;47&lt;/span&gt; LISTEN&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;TIME_WAIT 从 2.6 万降到 200 出头，端口耗尽问题彻底消失，下游调用成功率回到 99.99%。&lt;/p&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;应用层错误地使用 HTTP 客户端，导致对下游全部退化为短连接&lt;/strong&gt;，在流量翻倍后短连接产生速率超过 TIME_WAIT 回收速率，本地临时端口被 TIME_WAIT 占满，内核无法为新连接分配源端口，抛出 &lt;code&gt;EADDRNOTAVAIL&lt;/code&gt;（&lt;code&gt;cannot assign requested address&lt;/code&gt;）。&lt;/p&gt;&#xA;&lt;p&gt;内核默认的临时端口范围偏小、&lt;code&gt;tcp_tw_reuse&lt;/code&gt; 未开启，是放大问题的次要因素；但即使不调内核，只要连接正确复用，也不会触发此问题。所以内核调优是&amp;quot;缓解&amp;quot;，连接复用才是&amp;quot;根治&amp;quot;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;HTTP/DB/RPC 客户端一律复用&lt;/strong&gt;：使用全局单例 Client，显式配置连接池（尤其 &lt;code&gt;MaxIdleConnsPerHost&lt;/code&gt;），杜绝&amp;quot;每次请求 new 一个 client&amp;quot;。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控 TIME_WAIT 与端口水位&lt;/strong&gt;：把 &lt;code&gt;ss -ant state time-wait | wc -l&lt;/code&gt; 和临时端口范围利用率纳入监控，设置阈值告警（如占用 &amp;gt; 70% 报警），做到端口耗尽前就发现。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;合理设置内核参数&lt;/strong&gt;：客户端主机开启 &lt;code&gt;net.ipv4.tcp_tw_reuse=1&lt;/code&gt;、适当扩大 &lt;code&gt;ip_local_port_range&lt;/code&gt;；&lt;strong&gt;绝不启用&lt;/strong&gt; &lt;code&gt;tcp_tw_recycle&lt;/code&gt;（NAT 下会丢包，新内核已移除）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;压测覆盖连接维度&lt;/strong&gt;：上线前的压测不仅看 QPS 和延迟，还要观察连接状态分布，提前暴露短连接问题。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;区分错误语义&lt;/strong&gt;：把 &lt;code&gt;connection refused&lt;/code&gt;（对端拒绝）、&lt;code&gt;timeout&lt;/code&gt;（超时/丢包）、&lt;code&gt;cannot assign requested address&lt;/code&gt;（本机端口耗尽）在告警里分类，减少误判方向的时间。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;cannot assign requested address&lt;/code&gt; 是个非常&amp;quot;点题&amp;quot;的错误——它几乎总是在告诉你：不是网络问题，也不是对端问题，而是&lt;strong&gt;本机的临时端口不够用了&lt;/strong&gt;。这次故障的表象是下游调用失败，容易让人往网络和被调用方去查，但真正的病根在调用方自己的连接管理上。&lt;/p&gt;&#xA;&lt;p&gt;一句话经验：&lt;strong&gt;高并发服务，连接一定要复用&lt;/strong&gt;。TIME_WAIT 堆积、端口耗尽这类问题，内核参数只能缓解，正确复用连接才是根治之道。排查时先用 &lt;code&gt;ss -ant | sort | uniq -c&lt;/code&gt; 看一眼连接状态分布，往往几秒钟就能锁定方向。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>一次SSL/TLS证书过期导致全站HTTPS访问失败与API调用报证书错误的排查实录</title>
            <link>https://blog.5772447.xyz/posts/8f18423e/</link>
            <pubDate>Sat, 11 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/8f18423e/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司对外业务网关 &lt;code&gt;www.example.com&lt;/code&gt; 与多个内部微服务之间的相互调用均强制走 HTTPS。证书由 Let&amp;rsquo;s Encrypt 通过 certbot 自动签发，原本配置了 cron 定时续期，团队一直以为&amp;quot;证书会自动续，不用管&amp;quot;。某周一早晨 8 点多，陆续收到一线同事反馈与监控告警：官网打不开、移动端 App 登录失败、订单回调大面积超时。此时距离上次&amp;quot;证书无感知续期&amp;quot;已过去约 3 个月——而 Let&amp;rsquo;s Encrypt 证书有效期只有 90 天。这次，自动续期并没有像预期那样静默完成，而是已经连续失败了两三个月。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;浏览器访问 &lt;code&gt;https://www.example.com&lt;/code&gt; 被直接拦截，地址栏红色警告：&lt;code&gt;NET::ERR_CERT_DATE_INVALID&lt;/code&gt;，点开详情提示&amp;quot;证书已过期&amp;quot;。&lt;/li&gt;&#xA;&lt;li&gt;移动端 App 登录接口（&lt;code&gt;https://api.example.com/login&lt;/code&gt;）返回网络错误，抓包发现 TLS 握手阶段即被客户端中断。&lt;/li&gt;&#xA;&lt;li&gt;内部订单服务调用支付回调域名时，Java 侧抛出 &lt;code&gt;sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed&lt;/code&gt;（证书时间校验失败）。&lt;/li&gt;&#xA;&lt;li&gt;Nginx &lt;code&gt;error.log&lt;/code&gt; 出现大量 SSL 相关报错，但 Nginx 进程本身正常监听 443，说明不是服务挂了，而是证书本身失效。&lt;/li&gt;&#xA;&lt;li&gt;关键特征：故障是&amp;quot;突然全量爆发&amp;quot;而非渐进，且与当天发布无关——当天没有任何上线操作。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步，确认是不是证书过期。&lt;/strong&gt; 直接看对外域名的证书：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;echo | openssl s_client -servername www.example.com -connect www.example.com:443 2&amp;gt;/dev/null &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  | openssl x509 -noout -dates -subject&#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;# notBefore=May 12 00:13:42 2026 GMT&lt;/span&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;# notAfter=Aug 10 00:13:42 2026 GMT  ← 哎？还没过期？&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;咦，浏览器说过期，openssl 说没过期？这说明 443 上跑的证书根本不是我们以为的那张——前面还有一层 CDN / 负载均衡（SLB）在终结 TLS，客户端拿到的是 CDN 的证书，而源站 Nginx 证书是另一张。于是分别检查两端：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 看客户端真实拿到的（经 CDN）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -vI https://www.example.com 2&amp;gt;&amp;amp;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; | grep -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;expire\|subject&amp;#39;&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;# 直接打源站（绕过 CDN，用 hosts 或内网 IP）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo | openssl s_client -connect 10.20.30.40:443 &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  | openssl x509 -noout -enddate&#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;# notAfter=Jul 10 23:59:59 2026 GMT  ← 昨天到期！&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;真相浮现：CDN 回源到源站用的是一张独立签发的&lt;strong&gt;源站证书&lt;/strong&gt;，这张证书昨天 23:59 到期，而 CDN 对外证书是正常的。由于&amp;quot;全站 HTTPS 强制 + CDN 回源也强制 HTTPS&amp;quot;，一旦源站证书过期，CDN 回源握手失败，整站雪崩。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第二步，为什么自动续期没生效？&lt;/strong&gt; 查 certbot 续期日志与 cron：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;systemctl list-timers | grep certbot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;certbot renew --dry-run   &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;# 报错：Failed to bind to port 80 (HTTP-01 challenge) ... Address already in use&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;原来上季度新上线了一个内部运维平台，默认占用了 80 端口做 Web 管理，而 certbot 的 HTTP-01 校验需要临时监听 80 端口响应 ACME 挑战。新服务把 80 抢走了，certbot 续期连续两三个月都在凌晨静默失败，cron 的 stdout 被丢弃没人看，证书就这样悄悄走向过期。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步，确认影响面。&lt;/strong&gt; 不只 &lt;code&gt;www&lt;/code&gt; 和 &lt;code&gt;api&lt;/code&gt;，所有经 CDN 回源到源站 HTTPS 的域名（共 5 个）全部中招，因为源站证书是通配符 &lt;code&gt;*.example.com&lt;/code&gt; 单张，一损俱损。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;紧急止血（5 分钟）：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;临时让 CDN 回源改用 HTTP（关闭回源 HTTPS 校验），先把业务跑起来，代价是回源链路明文（内网可接受，限时）。&lt;/li&gt;&#xA;&lt;li&gt;同时把抢占 80 端口的运维平台改到 8080，腾出 80 给 certbot。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;彻底修复（30 分钟）：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 停掉占用 80 的服务后强制续期&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;systemctl stop ops-platform&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;certbot renew --force-renewal&#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;# 成功后立即把新证书 reload 进 Nginx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nginx -s reload&#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;# 恢复 CDN 回源 HTTPS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;验证：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;echo | openssl s_client -connect 10.20.30.40:443 &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  | openssl x509 -noout -enddate&#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;# notAfter=Oct 08 00:13:42 2026 GMT  ← 续上，90 天&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;curl -sI https://www.example.com | head -1  &lt;span style=&#34;color:#75715e&#34;&gt;# HTTP/2 200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&amp;quot;单点证书 + 续期依赖被悄悄破坏 + 缺乏过期监控&amp;quot;三件事叠加：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;全站回源强依赖一张源站证书，无冗余，证书一过期即全局故障——这是架构上的脆弱性。&lt;/li&gt;&#xA;&lt;li&gt;certbot HTTP-01 校验强依赖 80 端口，而 80 被新服务抢占后，续期失败但&lt;strong&gt;无任何告警&lt;/strong&gt;，形成&amp;quot;静默降级&amp;quot;。&lt;/li&gt;&#xA;&lt;li&gt;没有任何对证书剩余有效期的监控，过期前无提醒，只能等故障发生才发现。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控优先&lt;/strong&gt;：在 Prometheus/黑盒监控里加入证书有效期探针（ssl_exporter 或定期 &lt;code&gt;curl&lt;/code&gt; check），剩余 &lt;code&gt;&amp;lt; 21&lt;/code&gt; 天自动告警到 IM/电话。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;续期去端口化&lt;/strong&gt;：改用 DNS-01 校验（&lt;code&gt;certbot&lt;/code&gt; 的 &lt;code&gt;--dns&lt;/code&gt; 插件），不再依赖 80 端口，避免被其他服务干扰；或用 CNAME 把 &lt;code&gt;_acme-challenge&lt;/code&gt; 指向 certbot 托管区。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;解耦回源&lt;/strong&gt;：CDN 回源可短暂容忍自签/内部 CA 证书，或源站证书与对外证书分离并各自监控，避免单张证书拖垮全站。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;续期结果可见&lt;/strong&gt;：cron 里 &lt;code&gt;certbot renew&lt;/code&gt; 的退出码要接入监控，非 0 即告警，杜绝静默失败。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;缩短排障半径&lt;/strong&gt;：明确&amp;quot;CDN 对外证书 ≠ 源站证书&amp;quot;，建立证书台账（域名、签发方、到期日、责任人）。故障第一步先 &lt;code&gt;openssl x509 -enddate&lt;/code&gt; 比对客户端与实际终结点拿到的证书，而不是凭浏览器报错下结论。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障最&amp;quot;坑&amp;quot;的地方在于：现象是浏览器报证书过期，但 &lt;code&gt;openssl&lt;/code&gt; 直连却显示正常——因为中间隔了一层 CDN，客户端看到的证书和源站证书是两回事。排查 HTTPS 类问题，第一性原则是&amp;quot;分清 TLS 在哪一层被终结&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;另外，证书自动续期从来不是&amp;quot;配一次就高枕无忧&amp;quot;。只要续期链路上的任何依赖（端口、DNS、权限）被改动，它就会静默失效。把&amp;quot;证书有效期监控 + 续期结果告警&amp;quot;作为标配，远比依赖 cron 不报错来得靠谱。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>记一次 Kubernetes 因 liveness 探针配置过严导致 Pod 陷入 CrashLoopBackOff 的排查</title>
            <link>https://blog.5772447.xyz/posts/21e8a43e/</link>
            <pubDate>Sat, 11 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/21e8a43e/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;业务核心交易服务完成容器化改造，整体迁移到自建 Kubernetes 集群（v1.24，kubelet 运行时 containerd）。某次版本发布后，运维在发布系统里看到该服务的 Deployment 长时间处于 &lt;code&gt;Progressing&lt;/code&gt; 状态，副本数始终为 0/3。发布流水线反复重试仍无法拉起实例，上游网关已开始零星返回 502。由于当天还有其它变更在并行进行，最初的怀疑点被分散到了网络策略、镜像仓库和节点资源上，排查一度走偏。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;kubectl get pod -n trade&lt;/code&gt; 显示 3 个 Pod 全部处于 &lt;code&gt;CrashLoopBackOff&lt;/code&gt; 状态，&lt;code&gt;RESTARTS&lt;/code&gt; 列以肉眼可见的速度从 3、5、8 一路上涨，最短的十几秒就被重启一次。&lt;code&gt;kubectl describe pod&lt;/code&gt; 的 Events 里反复出现：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Liveness probe failed: HTTP probe failed with statusCode: 503&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Back-off restarting failed container&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;Pod 的 Conditions 中 &lt;code&gt;Ready&lt;/code&gt; 一直是 &lt;code&gt;False&lt;/code&gt;。有意思的是，用 &lt;code&gt;kubectl logs&lt;/code&gt; 看容器标准输出，发现应用进程其实在跑、日志里还在打印 &lt;code&gt;loading config / connecting to mysql&lt;/code&gt; 这类启动日志，并没有真正崩溃退出——它只是还没&amp;quot;活&amp;quot;过来就被杀掉了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，区分&amp;quot;进程崩溃&amp;quot;和&amp;quot;被探针杀掉&amp;quot;。因为 &lt;code&gt;RESTARTS&lt;/code&gt; 持续上涨但日志显示进程停在启动中途，基本可以排除 OOMKilled（OOM 会有 &lt;code&gt;OOMKilled&lt;/code&gt; 事件且通常不是稳定周期）。&lt;code&gt;kubectl describe&lt;/code&gt; 明确指向 &lt;code&gt;Liveness probe failed&lt;/code&gt;，方向锁定在探针。&lt;/p&gt;&#xA;&lt;p&gt;第二步，看探针配置。该 Deployment 的容器定义了 livenessProbe：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;livenessProbe&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;httpGet&lt;/span&gt;:&#xA;&lt;/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;/healthz&lt;/span&gt;&#xA;&lt;/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;8080&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;initialDelaySeconds&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#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;periodSeconds&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#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;failureThreshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;第三步，理解 &lt;code&gt;/healthz&lt;/code&gt; 的语义。这个端点并不是&amp;quot;进程还活着&amp;quot;的简单探测，而是开发在代码里把它实现成了&amp;quot;依赖全部就绪才算健康&amp;quot;——它内部会去连 MySQL、Redis 和配置中心 Nacos，任何一项没连上就返回 503。也就是说，&lt;code&gt;/healthz&lt;/code&gt; 实际上是一个 readiness 语义的端点被错误地用作了 liveness。&lt;/p&gt;&#xA;&lt;p&gt;第四步，核对应用真实启动耗时。应用是 Spring Boot 单体，冷启动到连上全部中间件、&lt;code&gt;/healthz&lt;/code&gt; 返回 200，平均需要 90 秒左右；而首次发布那天因为配置中心刚扩容、连接更慢，实测接近 120 秒。探针在容器启动后仅 10 秒就开始探活，连续 3 次（30 秒）失败就触发 kubelet 发 SIGTERM 杀容器。应用永远停在被 kill 在启动到一半的状态，下一轮重启又从 0 开始，陷入死循环。&lt;/p&gt;&#xA;&lt;p&gt;第五步，确认没有 readinessProbe。该容器只配了 liveness，没有 readinessProbe。即使某次侥幸启动完成，在 &lt;code&gt;/healthz&lt;/code&gt; 真正就绪前流量也会被 Service 转发进去，加剧不稳定。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;纠正探针语义：livenessProbe 改成只探&amp;quot;进程是否还活着、能否自救&amp;quot;，使用极轻量的端点（如独立的 &lt;code&gt;/health&lt;/code&gt;，仅返回 200，不依赖任何外部依赖），并把 &lt;code&gt;initialDelaySeconds&lt;/code&gt; 提高到 60，&lt;code&gt;failureThreshold&lt;/code&gt; 提到 5，给足启动宽容度。&lt;/li&gt;&#xA;&lt;li&gt;补上 readinessProbe：使用 &lt;code&gt;/healthz&lt;/code&gt;（依赖就绪才返回 200），&lt;code&gt;periodSeconds&lt;/code&gt; 10、&lt;code&gt;failureThreshold&lt;/code&gt; 3，确保只有真正就绪才接流量。&lt;/li&gt;&#xA;&lt;li&gt;引入 startupProbe 兜底慢启动：K8s 1.16+ 支持 startupProbe，在它探测成功之前，liveness 和 readiness 都不会生效。配置 &lt;code&gt;startupProbe&lt;/code&gt; &lt;code&gt;httpGet /healthz&lt;/code&gt;，&lt;code&gt;failureThreshold&lt;/code&gt; 30、&lt;code&gt;periodSeconds&lt;/code&gt; 5，相当于给应用最多 150 秒的启动窗口，期间不会被 liveness 误杀。&lt;/li&gt;&#xA;&lt;li&gt;开发侧拆分端点：明确 &lt;code&gt;/health&lt;/code&gt;（存活）、&lt;code&gt;/ready&lt;/code&gt;（就绪）两个语义不同的端点，避免把&amp;quot;就绪&amp;quot;逻辑塞进&amp;quot;存活&amp;quot;端点。&lt;/li&gt;&#xA;&lt;li&gt;滚动更新策略配合：把 &lt;code&gt;maxSurge&lt;/code&gt;/&lt;code&gt;maxUnavailable&lt;/code&gt; 调成 &lt;code&gt;1/0&lt;/code&gt;，避免新 Pod 没起来就把旧 Pod 摘掉造成容量空窗。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;改完重新发布，Pod 在约 100 秒后进入 &lt;code&gt;Running&lt;/code&gt;/&lt;code&gt;Ready&lt;/code&gt;，&lt;code&gt;RESTARTS&lt;/code&gt; 不再上涨，服务恢复。&lt;/p&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;探针语义错位 + 初始延迟远小于真实启动时间&lt;/strong&gt;。livenessProbe 的职责是&amp;quot;发现进程已死且无法自愈时重启它&amp;quot;，应该用最宽松的存活判断；而本例把&amp;quot;依赖全部就绪&amp;quot;这种 readiness 语义放进了 liveness，又只给 10 秒 &lt;code&gt;initialDelay&lt;/code&gt;，导致应用在依赖就绪前就被反复处决。本质是把&amp;quot;是否准备好接流量&amp;quot;和&amp;quot;进程是否还活着&amp;quot;两件事混为一谈。&lt;/p&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;给所有对外提供服务的容器同时配置 liveness / readiness / startup 三件套，语义严格区分。&lt;/li&gt;&#xA;&lt;li&gt;liveness 端点保持&amp;quot;零依赖&amp;quot;，只证明进程在跑；依赖就绪交给 readiness。&lt;/li&gt;&#xA;&lt;li&gt;启动慢的应用（连多数据源、拉配置中心）一律用 startupProbe 兜启动窗口，而不是无脑调大 &lt;code&gt;initialDelay&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;li&gt;把探针配置纳入上线 review 清单和 Chart 模板默认值，避免每个团队各写各的。&lt;/li&gt;&#xA;&lt;li&gt;在监控里对 Pod 的 &lt;code&gt;RESTARTS&lt;/code&gt; 速率、&lt;code&gt;CrashLoopBackOff&lt;/code&gt; 状态做告警，比等用户投诉早发现。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;CrashLoopBackOff 不一定意味着代码崩了，很多时候是探针在&amp;quot;帮倒忙&amp;quot;。liveness 要宽松、readiness 管流量、startup 管慢启动，三者各司其职，容器才稳。把&amp;quot;存活&amp;quot;和&amp;quot;就绪&amp;quot;混为一谈，是容器化迁移里最高频、也最隐蔽的坑之一。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>一次NFS存储服务端故障导致客户端进程陷入D状态业务整体假死的排查记录</title>
            <link>https://blog.5772447.xyz/posts/5961e223/</link>
            <pubDate>Fri, 10 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/5961e223/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司一套 OA 系统的附件服务，把用户上传的合同、扫描件等文件统一写到一台 NAS 上，客户端以 NFS 方式把 NAS 的 export 挂载到应用服务器的 &lt;code&gt;/data/attachment&lt;/code&gt; 目录。这套架构运行了两年多，平时应用线程只要 &lt;code&gt;write()&lt;/code&gt; 一下就能落盘，开发同学几乎忘了&amp;quot;本地磁盘&amp;quot;和&amp;quot;网络存储&amp;quot;的区别。&lt;/p&gt;&#xA;&lt;p&gt;变故发生在一次周二的上午。运维群里突然弹出一连串告警：附件服务 HTTP 接口 P99 耗时从平时的 200ms 涨到 30s 以上，超时率飙到 40%，连带依赖附件的审批流接口也开始大面积 5xx。但诡异的是，监控大盘上这台应用服务器的 &lt;strong&gt;CPU 利用率只有 15% 左右，内存也富余&lt;/strong&gt;，唯一异常的是 &lt;code&gt;load average&lt;/code&gt;——从平时的 4 左右一路爬到了 300 多。第一反应是&amp;quot;是不是被打了&amp;quot;，但 iptables 连接数、入口流量都正常，事情没那么简单。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;把现场能串起来的现象摊开看，至少有四条明显对不上&amp;quot;常规高负载&amp;quot;：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;接口超时但资源空闲&lt;/strong&gt;：应用 HTTP 层大量 &lt;code&gt;Read timed out&lt;/code&gt; / &lt;code&gt;AsyncRequestTimeoutException&lt;/code&gt;，然而 &lt;code&gt;top&lt;/code&gt; 里 CPU 大多数时间在 &lt;code&gt;id&lt;/code&gt;（空闲），&lt;code&gt;us&lt;/code&gt;/&lt;code&gt;sy&lt;/code&gt; 都不高——说明不是计算密集，而是线程&amp;quot;卡住&amp;quot;了。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;load average 离谱地高&lt;/strong&gt;：1 分钟负载一度冲到 380，但进程数并没有暴增。load 高通常意味着&amp;quot;运行队列 + 不可中断睡眠&amp;quot;的进程多，而这里明显是后者。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;部分命令直接卡死&lt;/strong&gt;：运维上机后想用 &lt;code&gt;df -h&lt;/code&gt; 看磁盘，&lt;code&gt;df&lt;/code&gt; 命令输出了本地盘后就&lt;strong&gt;卡住不动&lt;/strong&gt;，过了好几分钟才勉强结束；&lt;code&gt;ls /data/attachment&lt;/code&gt; 同样无响应。说明某个挂载点把进程&amp;quot;吸&amp;quot;住了。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;kill -9&lt;/code&gt; 杀不掉&lt;/strong&gt;：把几个明显不干活的应用 worker &lt;code&gt;kill -9&lt;/code&gt; 之后，进程&lt;strong&gt;依然存在&lt;/strong&gt;，状态栏显示一个 &lt;code&gt;D&lt;/code&gt;。这是整件事最关键的反常信号——连 SIGKILL 都杀不掉的进程，只可能处于不可中断睡眠。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-先确认是不是进程卡死而非忙死&#34;&gt;&lt;a href=&#34;#1-%e5%85%88%e7%a1%ae%e8%ae%a4%e6%98%af%e4%b8%8d%e6%98%af%e8%bf%9b%e7%a8%8b%e5%8d%a1%e6%ad%bb%e8%80%8c%e9%9d%9e%e5%bf%99%e6%ad%bb&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 先确认是不是进程&amp;quot;卡死&amp;quot;而非&amp;quot;忙死&amp;quot;&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;用 &lt;code&gt;top&lt;/code&gt; 按状态过滤，立刻看到一大片状态为 &lt;code&gt;D&lt;/code&gt;（即 &lt;code&gt;D = uninterruptible sleep&lt;/code&gt;，不可中断睡眠）的进程，而且这些进程的 &lt;code&gt;COMMAND&lt;/code&gt; 几乎都是 Java 应用的工作线程、日志滚动脚本，以及刚才那个卡住的 &lt;code&gt;df&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;top -b -n1 | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$8==&amp;#34;D&amp;#34;{print}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps -eo pid,ppid,stat,wchan:32,cmd | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$3==&amp;#34;D&amp;#34;&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;关键看 &lt;code&gt;WCHAN&lt;/code&gt; 列（进程当前睡眠在内核的哪个函数上），这些 D 状态进程清一色停在 &lt;code&gt;nfs&lt;/code&gt;、&lt;code&gt;rpc_wait_bit_killable&lt;/code&gt; 或 &lt;code&gt;fuse&lt;/code&gt; 相关的等待点上——&lt;strong&gt;全部和 NFS 客户端等待服务端回包有关&lt;/strong&gt;。再补一刀确认：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;cat /proc/&amp;lt;pid&amp;gt;/wchan      &lt;span style=&#34;color:#75715e&#34;&gt;# 输出类似于 nfs_wait_bit_killable&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat /proc/&amp;lt;pid&amp;gt;/stack      &lt;span style=&#34;color:#75715e&#34;&gt;# 内核栈能看到 nfs 调用链&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;2-锁定吸住的挂载点&#34;&gt;&lt;a href=&#34;#2-%e9%94%81%e5%ae%9a%e5%90%b8%e4%bd%8f%e7%9a%84%e6%8c%82%e8%bd%bd%e7%82%b9&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 锁定&amp;quot;吸住&amp;quot;的挂载点&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;既然 &lt;code&gt;df -h&lt;/code&gt; 会卡在挂载点，用 &lt;code&gt;mount&lt;/code&gt; 列出 NFS 挂载，并单独测试它：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;mount | grep nfs&#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;# 10.20.30.40:/volume1/oa_attach on /data/attachment type nfs ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;df -h /data/attachment     &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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;再开一个终端用 &lt;code&gt;strace&lt;/code&gt; 跟踪一个卡住的进程系统调用，看到它停在：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stat(&amp;#34;/data/attachment&amp;#34;,  &amp;lt;detached ...&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;符号非常明确：进程在 &lt;code&gt;stat()&lt;/code&gt; 这个 NFS 挂载点时，永远等不到服务端回复，于是挂在内核的 NFS 等待逻辑里。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-把怀疑下沉到-nfs-服务端&#34;&gt;&lt;a href=&#34;#3-%e6%8a%8a%e6%80%80%e7%96%91%e4%b8%8b%e6%b2%89%e5%88%b0-nfs-%e6%9c%8d%e5%8a%a1%e7%ab%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 把怀疑下沉到 NFS 服务端&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;既然客户端在等服务端，那就看服务端（NAS，10.20.30.40）是否还&amp;quot;活&amp;quot;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;ping 10.20.30.40                 &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;rpcinfo -p 10.20.30.40           &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;showmount -e 10.20.30.40         &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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;rpcinfo&lt;/code&gt; 和 &lt;code&gt;showmount&lt;/code&gt; 都走 RPC（端口 111 / 20048），它们卡住说明 &lt;strong&gt;NFS 服务端的 rpcbind / mountd / nfsd 已经不响应了&lt;/strong&gt;。再在客户端抓包确认请求是不是&amp;quot;肉包子打狗&amp;quot;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;tcpdump -nn -i any host 10.20.30.40 and port &lt;span style=&#34;color:#ae81ff&#34;&gt;2049&lt;/span&gt; -c &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&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;# 客户端不断发 NFS READ/WRITE，但服务端没有任何 ACK 回包&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;最后翻客户端内核日志，印证判断：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;dmesg -T | grep -i nfs&#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;# [Tue Jul  7 10:12:03] nfs: server 10.20.30.40 not responding, still trying&lt;/span&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;# [Tue Jul  7 10:12:31] nfs: server 10.20.30.40 not responding, still trying&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;日志里 &lt;code&gt;not responding, still trying&lt;/code&gt; 反复刷，是典型的 NFS 服务端无响应、客户端按 hard 语义死等的表现。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-服务端侧根因事后复盘&#34;&gt;&lt;a href=&#34;#4-%e6%9c%8d%e5%8a%a1%e7%ab%af%e4%be%a7%e6%a0%b9%e5%9b%a0%e4%ba%8b%e5%90%8e%e5%a4%8d%e7%9b%98&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 服务端侧根因（事后复盘）&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;登录 NAS 带外管理口查看，发现是&lt;strong&gt;一块磁盘出现介质错误，nfsd 工作线程在向后端文件系统刷写时被卡在底层 IO 上&lt;/strong&gt;，所有 nfsd 线程被这块坏盘拖死，对外不再响应任何新的 NFS 请求。也就是说：坏盘 → nfsd 线程阻塞 → NFS 服务端&amp;quot;假死&amp;quot; → 客户端 hard 挂载无限等待 → 进程 D 状态。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-先止血把挂载点从客户端摘掉&#34;&gt;&lt;a href=&#34;#1-%e5%85%88%e6%ad%a2%e8%a1%80%e6%8a%8a%e6%8c%82%e8%bd%bd%e7%82%b9%e4%bb%8e%e5%ae%a2%e6%88%b7%e7%ab%af%e6%91%98%e6%8e%89&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 先止血：把挂载点从客户端摘掉&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;当务之急是让几十上百个 D 状态进程解除阻塞。按风险从低到高：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 优先用 lazy umount，断开挂载点与目录的关联，正在等待的进程会拿到错误返回而解除 D 状态&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;umount -l /data/attachment&#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;umount -f /data/attachment&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;umount -l&lt;/code&gt;（lazy）是关键招：它不要求当前没有进程使用该挂载点，而是立刻把挂载点从命名空间摘下，之后等待中的进程在下次 IO 时会收到 I/O error 而醒来（虽仍可能被应用层重试逻辑再次卡住，但至少解除了内核层的死等）。执行后 &lt;code&gt;top&lt;/code&gt; 里 D 状态进程数迅速归零，load average 从 380 一路回落到个位数，HTTP 接口超时率也在几分钟内降到正常。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-恢复业务&#34;&gt;&lt;a href=&#34;#2-%e6%81%a2%e5%a4%8d%e4%b8%9a%e5%8a%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 恢复业务&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;临时把附件写入切到本地盘（&lt;code&gt;mount --bind&lt;/code&gt; 一个本地目录顶上，或改应用配置指向本地路径），让审批流先恢复；同时通知 NAS 管理员重启 &lt;code&gt;nfs-server&lt;/code&gt; 服务、隔离坏盘、修复 RAID。服务端 nfsd 恢复响应后，再重新挂载：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;mount -t nfs 10.20.30.40:/volume1/oa_attach /data/attachment&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;整条故障链的源头有两点，缺一不可：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务端侧&lt;/strong&gt;：NAS 单盘故障导致 nfsd 线程被后端 IO 阻塞，NFS 服务整体失去响应能力，且服务端本身没有对 nfsd 线程做隔离/超时保护。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;客户端侧（更关键的放大因素）&lt;/strong&gt;：Linux NFS 客户端&lt;strong&gt;默认是 hard 挂载&lt;/strong&gt;（&lt;code&gt;hard&lt;/code&gt; 而非 &lt;code&gt;soft&lt;/code&gt;）。hard 模式下，NFS 请求如果得不到服务端确认，客户端会&lt;strong&gt;无限重试、永不放弃&lt;/strong&gt;，对应进程进入 &lt;code&gt;TASK_UNINTERRUPTIBLE&lt;/code&gt;（D 状态）。一旦进入 D 状态，&lt;code&gt;SIGKILL&lt;/code&gt; 也无效——因为内核不允许进程在等待关键 IO 时被中途掐掉。结果就是：一个服务端故障，被 hard 语义放大成客户端成百上千个进程永久卡死、load 爆表、业务整体假死。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;换句话说，这不是&amp;quot;客户端扛不住&amp;quot;，而是&lt;strong&gt;客户端对存储故障缺乏兜底&lt;/strong&gt;：它把&amp;quot;网络存储临时不可用&amp;quot;当成了&amp;quot;必须无限等待&amp;quot;的硬约束。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障之后，我们从客户端、服务端、架构三层做了加固：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;客户端挂载加容错参数&lt;/strong&gt;：把默认 hard 改为 soft 并加超时与重试，避免无限等待：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# /etc/fstab 示例（注意 soft + timeo + retrans + retry）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;10.20.30.40:/volume1/oa_attach  /data/attachment  nfs  soft,timeo&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;30,retrans&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3,retry&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;2,_netdev  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;timeo=30&lt;/code&gt; 表示每次 RPC 超时 3 秒（单位是 0.1s），&lt;code&gt;retrans=3&lt;/code&gt; 重试 3 次后返回错误，&lt;code&gt;retry=2&lt;/code&gt; 限制挂载阶段重试。这样 NFS 不可用时进程会&lt;strong&gt;快速失败&lt;/strong&gt;而不是永久 D 住。&lt;code&gt;_netdev&lt;/code&gt; 保证网络就绪后再挂载、关机时先 umount。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;监控要能抓到 D 状态&lt;/strong&gt;：在 Node Exporter 之外补充采集 &lt;code&gt;D&lt;/code&gt; 状态进程数和 &lt;code&gt;load1&lt;/code&gt;，一旦 D 状态进程数 &amp;gt; 0 持续超过阈值就告警——这是 NFS 类故障最早的信号，比 HTTP 超时早得多。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;对挂载点做存活探测&lt;/strong&gt;：用 &lt;code&gt;timeout&lt;/code&gt; 包裹的 &lt;code&gt;stat&lt;/code&gt; 定时探 &lt;code&gt;/data/attachment&lt;/code&gt;，或部署监控脚本在探测超时时自动 &lt;code&gt;umount -l&lt;/code&gt; 兜底，避免人工响应不及时。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;服务端高可用&lt;/strong&gt;：NAS 侧对 nfsd 做进程级健康检查与自动重启；重要业务改用双机 + 共享存储（如 DRBD）或直接使用对象存储（S3/S3 兼容）替代 NFS 共享，从根本上消除&amp;quot;单存储挂掉拖垮应用&amp;quot;的强耦合。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;应用层解耦&lt;/strong&gt;：附件写入增加本地缓冲队列与异步刷盘，NFS 不可用时先落本地、恢复后再同步，避免业务线程直接同步阻塞在远程存储上。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障最&amp;quot;反直觉&amp;quot;的地方在于：&lt;strong&gt;监控上 CPU、内存都正常，业务却整体假死&lt;/strong&gt;。根因不在算力，而在 NFS 客户端默认的 hard 挂载语义——它把&amp;quot;存储暂时不可用&amp;quot;翻译成了&amp;quot;进程永久等待&amp;quot;。排查的关键三步是：&lt;code&gt;top&lt;/code&gt; 抓 D 状态进程 → &lt;code&gt;wchan&lt;/code&gt;/&lt;code&gt;stack&lt;/code&gt; 确认卡在 NFS 等待 → &lt;code&gt;rpcinfo&lt;/code&gt;/&lt;code&gt;tcpdump&lt;/code&gt;/&lt;code&gt;dmesg&lt;/code&gt; 证明服务端无响应。止血用 &lt;code&gt;umount -l&lt;/code&gt; 立竿见影。&lt;/p&gt;&#xA;&lt;p&gt;记住一条运维铁律：&lt;strong&gt;凡是跨网络的文件系统挂载，默认 hard 都是隐患；要么加 soft + 超时重试，要么让应用在存储故障时能快速失败而不是永久等待。&lt;/strong&gt; 否则，一个远端的坏盘，就足以让你的整台应用服务器&amp;quot;活着但死了&amp;quot;。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>一次内网 DNS 转发链路异常导致核心业务系统间歇解析超时与偶发 504 的排查记录</title>
            <link>https://blog.5772447.xyz/posts/fb53e550/</link>
            <pubDate>Thu, 09 Jul 2026 16:58:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/fb53e550/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司核心交易链路里有一批微服务（跑在 K8s 上，也有部分裸金属虚拟机），它们调用多家三方能力：支付网关、短信通道、地图地理编码、风控评分等。这些三方域名全部走公网域名解析，集群内的 &lt;code&gt;/etc/resolv.conf&lt;/code&gt; 统一指向自建内网 DNS 转发器（基于 CoreDNS，上游为两个运营商递归 + 一个公共递归 119.19.19.19）。这套解析体系已经稳定运行一年，平时解析成功率在 99.9% 以上，P99 解析延迟 &amp;lt; 30ms。&lt;/p&gt;&#xA;&lt;p&gt;变故出现在一次大促前的压测期间。订单服务在压到日常 3 倍流量时，监控里开始零星冒出上游 504（Gateway Timeout），每天约几十笔，分散在不同时段、不同节点，单笔失败率不到 0.1%，但恰好都集中在“调用三方 API”的环节。因为量太小、又不可复现，前两周一直被当成“三方接口抖动”挂了外部工单，直到大促临近，我们决定把它彻底查清楚。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;现场能串起来的现象有四条，且都指向“解析”而非“后端慢”：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;业务层偶发 504&lt;/strong&gt;：订单服务调支付/短信时，HTTP 客户端抛 &lt;code&gt;upstream connect error or disconnect/reset before headers&lt;/code&gt; 或 &lt;code&gt;504&lt;/code&gt;，但后端真实接口监控一切正常，三方厂商侧也查不到对应请求日志——说明请求压根没出公司网络。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;应用侧报解析失败&lt;/strong&gt;：在出问题的 Pod 里手动 &lt;code&gt;curl -v https://api.sms-provider.com&lt;/code&gt;，约 3%~5% 概率直接返回 &lt;code&gt;curl: (6) Could not resolve host: api.sms-provider.com&lt;/code&gt;；同一个域名重试一次又好了。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;只在特定时段更频繁&lt;/strong&gt;：压测或晚高峰（出口带宽吃紧时）失败率明显上升，闲时几乎为 0。这暗示问题跟“链路质量/拥塞”有关，而非单纯配置错。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并非所有域名都中招&lt;/strong&gt;：公司自有的 &lt;code&gt;*.internal&lt;/code&gt; 和内网服务发现域名从不失败，只有走公网递归的三方域名会偶发失败——范围被天然缩小到“内网 DNS 转发器 → 公网递归”这一段。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;最关键是：它是&lt;strong&gt;间歇性&lt;/strong&gt;的，单看任何一时刻的监控都不算“故障”，必须靠抓包和统计才能暴露规律。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-先确认是不是应用端的问题&#34;&gt;&lt;a href=&#34;#1-%e5%85%88%e7%a1%ae%e8%ae%a4%e6%98%af%e4%b8%8d%e6%98%af%e5%ba%94%e7%94%a8%e7%ab%af%e7%9a%84%e9%97%ae%e9%a2%98&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 先确认是不是应用端的问题&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;先排除应用自身：在出问题的节点上循环 &lt;code&gt;curl&lt;/code&gt; 一个三方域名 200 次，统计失败率，同时开着应用日志对照。结果是 curl 本身的失败率（4.1%）与应用层 504 的失败率高度吻合，且 curl 失败全是 &lt;code&gt;Could not resolve host&lt;/code&gt;。&lt;strong&gt;基本锁定：问题在 DNS 解析环节，不在业务代码、不在 LB、不在三方接口。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-抓包看-dns-到底丢没丢&#34;&gt;&lt;a href=&#34;#2-%e6%8a%93%e5%8c%85%e7%9c%8b-dns-%e5%88%b0%e5%ba%95%e4%b8%a2%e6%b2%a1%e4%b8%a2&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 抓包看 DNS 到底丢没丢&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在节点上 &lt;code&gt;tcpdump&lt;/code&gt; 抓 DNS 流量，复现失败那一刻：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;tcpdump -i eth0 -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;udp port 53&amp;#39;&lt;/span&gt; -w /tmp/dns.pcap &amp;amp;&#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;for&lt;/span&gt; i in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;seq &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; 200&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; dig +short @&amp;lt;内网DNS&amp;gt; api.sms-provider.com; &lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;用 Wireshark 打开 pcap，现象非常清晰：&lt;strong&gt;约 4% 的 DNS 查询发出后，在 5 秒超时（转发器 &lt;code&gt;timeout&lt;/code&gt; 设的 5s）内没有任何响应返回，然后客户端重试一次才成功。&lt;/strong&gt; 也就是说，内网 DNS 把请求转给上游后，上游“哑了”。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-定位到内网-dns--上游这一段&#34;&gt;&lt;a href=&#34;#3-%e5%ae%9a%e4%bd%8d%e5%88%b0%e5%86%85%e7%bd%91-dns--%e4%b8%8a%e6%b8%b8%e8%bf%99%e4%b8%80%e6%ae%b5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 定位到“内网 DNS → 上游”这一段&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;直接用 &lt;code&gt;dig&lt;/code&gt; 把枪口对准转发器上游，连续探测并统计：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i in &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;seq &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; 300&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  dig +nocmd +stats +time&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; +tries&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; @119.19.19.19 api.sms-provider.com | grep -E &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Query time|status&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:#66d9ef&#34;&gt;done&lt;/span&gt; | sort | uniq -c&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;结果：&lt;code&gt;Query time&lt;/code&gt; 在 8ms~200ms 之间抖动，但有约 4% 的探测&lt;strong&gt;根本没有 &lt;code&gt;Query time&lt;/code&gt; 行&lt;/strong&gt;（即超时无响应），与业务失败率吻合。换成另一个运营商上游，失败率类似但略低（2%）。结论：&lt;strong&gt;两条上游链路都偶发丢包，且转发器只有这两条、无备用、无快速失败切换。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-为什么偏偏是某些域名更容易丢&#34;&gt;&lt;a href=&#34;#4-%e4%b8%ba%e4%bb%80%e4%b9%88%e5%81%8f%e5%81%8f%e6%98%af%e6%9f%90%e4%ba%9b%e5%9f%9f%e5%90%8d%e6%9b%b4%e5%ae%b9%e6%98%93%e4%b8%a2&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 为什么“偏偏是某些域名”更容易丢&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;进一步对比：对 &lt;code&gt;api.sms-provider.com&lt;/code&gt; 这类容易失败的域名，和 &lt;code&gt;www.baidu.com&lt;/code&gt; 这类几乎不失败的域名，分别用不同 &lt;code&gt;bufsize&lt;/code&gt; 探测：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 关闭 EDNS0（强制 512 字节传统响应）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dig +noedns @119.19.19.19 api.sms-provider.com +stats&#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;# 开启 EDNS0 并放大缓冲区&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dig +bufsize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; @119.19.19.19 api.sms-provider.com +stats&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;差异显著：&lt;code&gt;+noedns&lt;/code&gt; 时失败率几乎归零；&lt;code&gt;+bufsize=4096&lt;/code&gt; 时失败率飙到 8% 以上。再结合 &lt;code&gt;dig +trace&lt;/code&gt; 看到该域名返回了大量 A/AAAA 记录且开启了 DNSSEC，响应包体积常超过 1200 字节。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;根因线索浮现&lt;/strong&gt;：内网 DNS 转发器开了 EDNS0，向运营商递归请求大响应；但中间某一跳（运营商出口或公司边界防火墙）会对 &lt;strong&gt;UDP 53 上 &amp;gt;512 字节的包做分片/限速/丢弃&lt;/strong&gt;，导致大响应在回程被吃掉。UDP 本身无重传，于是这次查询“凭空消失”，只能等转发器 5s 超时后客户端重试——而重试往往走不同路径或不同上游，所以“重试一次就好了”。&lt;/p&gt;&#xA;&lt;h3 id=&#34;5-验证-tcp-fallback-能否救场&#34;&gt;&lt;a href=&#34;#5-%e9%aa%8c%e8%af%81-tcp-fallback-%e8%83%bd%e5%90%a6%e6%95%91%e5%9c%ba&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;5. 验证 TCP fallback 能否救场&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;EDNS0 大包在 UDP 上被丢，理论上 DNS 应自动降级到 TCP 53 重传。但实测发现转发器对超时的处理是“傻等超时再让客户端重试”，自己并不会主动切 TCP 或切备用上游；且公司边界防火墙&lt;strong&gt;默认只放行了 UDP 53，没放行 TCP 53&lt;/strong&gt;，导致即使想 fallback 也连不上。用 &lt;code&gt;dig +tcp @上游 域名&lt;/code&gt; 验证：TCP 路径 100% 成功，彻底坐实“UDP 大包被丢、TCP 正常”的判断。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1-立刻止血收敛-edns0-包体积--多上游&#34;&gt;&lt;a href=&#34;#1-%e7%ab%8b%e5%88%bb%e6%ad%a2%e8%a1%80%e6%94%b6%e6%95%9b-edns0-%e5%8c%85%e4%bd%93%e7%a7%af--%e5%a4%9a%e4%b8%8a%e6%b8%b8&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 立刻止血：收敛 EDNS0 包体积 + 多上游&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;修改 CoreDNS 转发配置（&lt;code&gt;Corefile&lt;/code&gt;），把 EDNS0 缓冲区压到 MTU 安全值 1232，并配置多上游 + 合理超时：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.:53 {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    forward . 119.19.19.19 223.5.5.5 1.1.1.1 {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        max_fails 3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        expire 10s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        policy random&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        health_check 5s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        # 限制 EDNS0 缓冲区，避免大包在中间网络被分片丢弃&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bufsize 1232&#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;        timeout 2s&#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;    cache 30&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    errors&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    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;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;bufsize 1232&lt;/code&gt; 是 1500 MTU 减去 IP/UDP 头后的安全上限，确保响应不需要 IP 分片；&lt;code&gt;timeout 2s&lt;/code&gt; + 多上游让单条链路丢包时快速切走，而不是干等 5 秒。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2-放开-tcp-53启用-fallback&#34;&gt;&lt;a href=&#34;#2-%e6%94%be%e5%bc%80-tcp-53%e5%90%af%e7%94%a8-fallback&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 放开 TCP 53，启用 fallback&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在边界防火墙放通 DNS 的 TCP 53（不只是 UDP），并在转发器层面确认大响应超 UDP 时能走 TCP 重传。验证：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 强制 TCP 探测，成功率应 100%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dig +tcp +bufsize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; @119.19.19.19 api.sms-provider.com +stats&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;3-客户端兜底缩短超时与重试&#34;&gt;&lt;a href=&#34;#3-%e5%ae%a2%e6%88%b7%e7%ab%af%e5%85%9c%e5%ba%95%e7%bc%a9%e7%9f%ad%e8%b6%85%e6%97%b6%e4%b8%8e%e9%87%8d%e8%af%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 客户端兜底：缩短超时与重试&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在节点 &lt;code&gt;resolv.conf&lt;/code&gt; 上加保守参数，避免单点 DNS 抖动拖垮整个调用：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;options timeout:1 attempts:2 rotate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;K8s 场景则通过 &lt;code&gt;kubelet --resolv-conf&lt;/code&gt; 或 Pod &lt;code&gt;dnsConfig&lt;/code&gt; 下发同样的 &lt;code&gt;options&lt;/code&gt;，让解析失败快速重试到另一个转发器实例。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-关键三方域名本地缓存兜底&#34;&gt;&lt;a href=&#34;#4-%e5%85%b3%e9%94%ae%e4%b8%89%e6%96%b9%e5%9f%9f%e5%90%8d%e6%9c%ac%e5%9c%b0%e7%bc%93%e5%ad%98%e5%85%9c%e5%ba%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 关键三方域名本地缓存兜底&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;对支付、短信这类核心且域名固定的三方，在 CoreDNS 用 &lt;code&gt;hosts&lt;/code&gt; 或 &lt;code&gt;file&lt;/code&gt; 插件做本地静态兜底，即便公网递归全挂也能解析，把“外部依赖”降级为“本地可控”。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;本质是**“单点上游 + EDNS0 大包在中间网络被丢弃 + 缺乏快速失败/备用链路”**三者叠加。内网 DNS 转发器开启了 EDNS0 并请求大响应，而运营商出口/边界防火墙对 UDP 53 上的大包做了分片或限速丢弃；UDP 无重传，导致约 3%~5% 的查询在回程“凭空消失”。转发器又只有单/双上游、超时长达 5 秒且不主动切 TCP/备用，于是把“一次解析超时”放大成了“应用侧 5 秒白等 → 上游 504”。失败只有在“出口拥塞或大响应域名”时才显著，因此呈现出难复现的间歇性特征。问题不在三方接口、不在业务代码，而在 DNS 转发链路的一条隐蔽 UDP 路径。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;DNS 高可用&lt;/strong&gt;：转发器至少配 2~3 个不同运营商/公共递归上游，开启 &lt;code&gt;health_check&lt;/code&gt; 与健康剔除，单链路丢包时秒级切走；转发器本身也部署多实例 + Service 负载均衡。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;控制 EDNS0 包体积&lt;/strong&gt;：&lt;code&gt;bufsize&lt;/code&gt; 统一设为 1232，从源头规避 UDP 分片被丢；同时放通 TCP 53，保证大响应能走 TCP 可靠传输。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控解析质量而非只看“能通”&lt;/strong&gt;：用 Prometheus + blackbox_exporter 对核心三方域名做持续 DNS 探测，把 &lt;code&gt;probe_success&lt;/code&gt;、解析延迟 P99 接入告警，对失败率 &amp;gt; 1% 即时报警，而不是等业务 504 才察觉。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;客户端防御性配置&lt;/strong&gt;：&lt;code&gt;resolv.conf&lt;/code&gt; 设 &lt;code&gt;timeout:1 attempts:2 rotate&lt;/code&gt;，缩短单点抖动的影响窗口；容器场景统一通过 &lt;code&gt;dnsConfig&lt;/code&gt; 下发。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;关键域名本地兜底&lt;/strong&gt;：核心三方域名用 &lt;code&gt;hosts&lt;/code&gt;/&lt;code&gt;file&lt;/code&gt; 插件做静态解析兜底，外部递归全断也不影响主链路。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;复盘中补充的边界项&lt;/strong&gt;：防火墙策略变更必须同步 DNS 的 TCP/UDP 双端口放行，避免“放 UDP 忘 TCP”这类隐性单点。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障的典型之处在于：&lt;strong&gt;业务报的是 504，根因却藏在 DNS 转发器一个 UDP 包被丢的瞬间&lt;/strong&gt;。它不报错、不宕机，只在出口拥塞或大响应域名上偶发，单看监控谁都像“无辜”。给运维的启示是——遇到“三方接口偶发超时、但对方查无此请求”的现象，要敢于从应用层一路下沉到 DNS/UDP 链路，用 &lt;code&gt;tcpdump&lt;/code&gt; + &lt;code&gt;dig +stats&lt;/code&gt; 把“丢包率”这项指标量化出来；同时 DNS 这种“看似简单”的基础设施，恰恰最该做多上游、控包体、开 TCP、配监控，别让一条被丢弃的 UDP 53 包，悄悄拖垮整条交易链路。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>一次办公网DHCP地址池耗尽导致部分终端无法获取IP的排查记录</title>
            <link>https://blog.5772447.xyz/posts/018de7f4/</link>
            <pubDate>Wed, 08 Jul 2026 07:00:00 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/018de7f4/</guid>
            <description>&lt;h2 id=&#34;问题背景&#34;&gt;&lt;a href=&#34;#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司办公网核心是一台三层交换机，下挂多个接入交换机，员工 PC、手机、打印机和一堆 IoT 设备都划分在同一个 /24 网段里，由 Windows Server 上的 DHCP 服务统一下发地址。平时一切正常，管理员也没太关注地址池的剩余量。某天周一早高峰，几乎同一时刻上百人打卡开机、连 WiFi，问题就爆发了。这类&amp;quot;容量型&amp;quot;故障最隐蔽的地方在于：它平时毫无征兆，一旦触发就是大面积、且每次重启都只是暂时缓解，很容易让排障者陷入&amp;quot;重启试试&amp;quot;的误区。&lt;/p&gt;&#xA;&lt;h2 id=&#34;故障现象&#34;&gt;&lt;a href=&#34;#%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;早上 9 点前后，IT 服务台在十分钟内涌进二十多个报障工单，集中在同一楼层：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;部分员工插上网线或连上办公 WiFi 后，系统托盘网络图标显示&amp;quot;黄色感叹号&amp;quot;，状态是&amp;quot;已连接，但无法访问 Internet&amp;quot;；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ipconfig /all&lt;/code&gt; 看到的不是正常的 &lt;code&gt;192.168.10.x&lt;/code&gt;，而是 &lt;code&gt;169.254.x.x&lt;/code&gt;（APIPA 自动专用地址），说明没有从 DHCP 拿到地址；&lt;/li&gt;&#xA;&lt;li&gt;能 Ping 通网关 &lt;code&gt;192.168.10.1&lt;/code&gt;，但打不开任何网页，DNS 解析也失败；&lt;/li&gt;&#xA;&lt;li&gt;已在线的人不受影响，问题只集中在新开机、或休眠唤醒、或重新连网的那批终端；&lt;/li&gt;&#xA;&lt;li&gt;现场重启交换机、重启网卡后能临时恢复，但半小时后同样的人又掉回 169.254，形成&amp;quot;重启救一时、过会儿又复发&amp;quot;的怪圈。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;初步判断这不是线路或交换机故障——能 Ping 通网关就说明二层、三层转发是好的，问题大概率出在&amp;quot;地址下发&amp;quot;这一环。&lt;/p&gt;&#xA;&lt;h2 id=&#34;排查过程&#34;&gt;&lt;a href=&#34;#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步：确认是否真的没拿到地址。&lt;/strong&gt; 在故障终端上执行 &lt;code&gt;ipconfig /release &amp;amp;&amp;amp; ipconfig /renew&lt;/code&gt;，观察输出。正常情况下会立刻拿到 &lt;code&gt;192.168.10.x&lt;/code&gt;；而故障终端卡在 &amp;ldquo;正在等待 DHCP 服务器响应&amp;rdquo; 几十秒后，退回 169.254.x.x。结合 &lt;code&gt;ipconfig /all&lt;/code&gt; 里&amp;quot;自动配置 IP 地址 169.254.x.x&amp;quot;，基本锁定：DHCP  Discover/Offer 阶段就拿不到地址，不是 DNS 也不是网关问题。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第二步：直奔 DHCP 服务器看地址池。&lt;/strong&gt; 登录 Windows DHCP 控制台（或 &lt;code&gt;dhcputil&lt;/code&gt; / PowerShell &lt;code&gt;Get-DhcpServerv4Scope&lt;/code&gt;），展开作用域 &lt;code&gt;192.168.10.0/24&lt;/code&gt;，重点看两个数字：&lt;strong&gt;&amp;ldquo;地址总数&amp;rdquo;&lt;/strong&gt; 与 &lt;strong&gt;&amp;ldquo;可用地址&amp;rdquo;&lt;/strong&gt;。结果发现：253 个可用地址里，剩余可用显示为 &lt;strong&gt;0&lt;/strong&gt;，租约列表里 253 条全是&amp;quot;已租用 (Active)&amp;ldquo;状态。这就对上了——不是服务器宕了，而是它&amp;quot;无地址可发&amp;rdquo;，只能让客户端退到 APIPA。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步：分析租约构成，找出&amp;quot;占坑&amp;quot;的设备。&lt;/strong&gt; 把租约按&amp;quot;租约过期时间&amp;quot;排序，发现大量租约剩余时间还挂着 6~7 天（默认租期 8 天），且客户端标识里混着很多手机 MAC（OUI 一眼能认出是 Apple / Xiaomi / Huawei）、几台访客笔记本、十几台打印机和智能电视。也就是说：一个 /24 既要养员工 PC，又要养所有人的手机、访客设备、IoT，253 个地址根本不够早高峰并发。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第四步：确认有没有&amp;quot;放大器&amp;quot;。&lt;/strong&gt; 进一步排查发现，有员工在工位私接了一台家用无线路由器当 AP，LAN 口又接回办公网——这本身不直接耗地址，但更严重的是另一处：访客 WiFi 的 DHCP 中继（DHCP Relay / IP Helper）错误地指向了办公网这个作用域，导致访客手机也来抢办公地址。再加上几个研发在测试环境开了几十台虚拟机，桥接到了办公网桥，每台都来要地址。三重叠加，地址池直接被打满。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第五步：用数据验证根因。&lt;/strong&gt; 在核心交换机上 &lt;code&gt;show ip dhcp snooping binding&lt;/code&gt;（或 Windows 侧用 &lt;code&gt;Get-DhcpServerv4Lease -ScopeId 192.168.10.0 | Measure-Object&lt;/code&gt;），统计当前活跃租约里非员工 PC 的占比，超过 55%。结合早高峰工单时间曲线与租约申请日志峰值时间完全吻合，确认&amp;quot;地址池容量不足 + 租期过长 + 访客/测试流量串入&amp;quot;是本次故障的组合根因。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案&#34;&gt;&lt;a href=&#34;#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;排障要快、根治要稳，分两步走：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;应急（10 分钟内恢复业务）：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;在 DHCP 控制台对抢占严重的访客 MAC、测试虚拟机 MAC 做&lt;strong&gt;保留排除（Reservation / Exclusion）&lt;/strong&gt;，把它们从办公作用域剔除；&lt;/li&gt;&#xA;&lt;li&gt;临时把办公作用域的&lt;strong&gt;租期从 8 天改成 8 小时&lt;/strong&gt;，&lt;code&gt;Set-DhcpServerv4Scope -LeaseDuration 08:00:00&lt;/code&gt;，让休眠/离线的设备更快释放地址；&lt;/li&gt;&#xA;&lt;li&gt;立即修正访客 WiFi 的 DHCP Relay，指向独立的访客作用域，并给研发测试网单独划 VLAN、单独地址池；&lt;/li&gt;&#xA;&lt;li&gt;对仍卡在 169.254 的终端批量 &lt;code&gt;ipconfig /release &amp;amp;&amp;amp; ipconfig /renew&lt;/code&gt;，几分钟内全部恢复正常。&lt;/li&gt;&#xA;&lt;/ol&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;拆分 VLAN&lt;/strong&gt;，把办公、访客、IoT、打印机分属不同子网，每个子网独立 /24，从物理上隔离地址竞争；&lt;/li&gt;&#xA;&lt;li&gt;启用接入交换机的 &lt;strong&gt;DHCP Snooping + 端口安全&lt;/strong&gt;，非法私接的路由器/小交换机无法下发地址，从源头堵住&amp;quot;家用路由当 AP&amp;quot;的乱接行为；&lt;/li&gt;&#xA;&lt;li&gt;对固定设备（打印机、服务器、AP）做静态保留，把动态池留给真正的流动终端。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;根因分析&#34;&gt;&lt;a href=&#34;#%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根本原因是&lt;strong&gt;地址规划与容量管理缺位&lt;/strong&gt;，而非设备故障：单个 /24（253 地址）承载了远超设计容量的终端类型，且默认 8 天租期让离线设备长期&amp;quot;占坑不释放&amp;quot;；同时访客网络与测试网络的 DHCP 流量错误串入办公作用域，成了压垮地址池的最后一根稻草。169.254 只是表象，地址池归零才是真凶。&lt;/p&gt;&#xA;&lt;h2 id=&#34;预防措施&#34;&gt;&lt;a href=&#34;#%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;容量规划前置&lt;/strong&gt;：按&amp;quot;终端数 × 1.3&amp;quot;预留地址，移动设备多的办公区直接上 /23 或拆 VLAN，别拿一个 /24 硬扛；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;租期分级&lt;/strong&gt;：员工 PC 可长（如 1 天），手机/访客用短租期（2~4 小时），让地址快速周转；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;网络分区&lt;/strong&gt;：办公、访客、IoT、打印严格分 VLAN，各用各的地址池，互不影响；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控告警&lt;/strong&gt;：对 DHCP 作用域的&amp;quot;可用地址数&amp;quot;做监控，低于 20% 就告警，把故障消灭在爆发前；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;接入管控&lt;/strong&gt;：开启 DHCP Snooping + 端口安全，禁止私接 NAT 路由，避免地址池被意外放大消耗。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;总结&#34;&gt;&lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;DHCP 地址池耗尽是典型&amp;quot;平时无感、爆发致命&amp;quot;的容量型故障，排查关键就一句话：&lt;strong&gt;看到 169.254，先别查线路，直接去 DHCP 服务器看&amp;quot;可用地址&amp;quot;是不是 0&lt;/strong&gt;。真正要做的不是反复重启，而是缩短租期、隔离访客、拆 VLAN、加监控——把容量和管理补齐，故障才不会下个周一再来一遍。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;em&gt;本文基于真实办公网排障场景整理，涉及 IP 段与设备数量已做脱敏处理。&lt;/em&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>Docker 宿主机 overlay2 inode 耗尽致容器批量创建失败的定位</title>
            <link>https://blog.5772447.xyz/posts/7c34ba61/</link>
            <pubDate>Tue, 07 Jul 2026 12:38:41 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/7c34ba61/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司内部的 CI/CD 构建节点是一台 2C4G 的云主机，上面跑着 GitLab Runner，所有流水线任务都通过 &lt;code&gt;docker run&lt;/code&gt; 临时拉起容器执行编译、单元测试和镜像打包。这台机器已经稳定运行了半年多，运维也基本是&amp;quot;放养&amp;quot;状态——除了偶尔手动清理一下磁盘，没人专门维护。某天上午，开发同学突然在群里反馈：多条流水线同时失败，报错信息五花八门，有的说&amp;quot;无法拉取镜像&amp;quot;，有的说&amp;quot;容器启动超时&amp;quot;。我登录上去一看，连 &lt;code&gt;docker ps&lt;/code&gt; 都开始变得卡顿，这才意识到事情没那么简单。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;最直观的现象是：几乎所有新建容器的操作都会失败。无论是 Runner 自动拉起的构建容器，还是我手动执行的 &lt;code&gt;docker run hello-world&lt;/code&gt;，都返回一个类似的错误：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker: Error response from daemon: mkdir /var/lib/docker/overlay2/xxxxxxx: no space left on device.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;更诡异的是，报错明明说 &amp;ldquo;no space left on device（设备上没有剩余空间）&amp;quot;，但 &lt;code&gt;df -h /&lt;/code&gt; 显示的磁盘使用率只有 63%，还有大把空间。开发同学一度怀疑是 Docker 引擎抽风，甚至有人建议直接重启机器&amp;quot;试试看&amp;rdquo;。&lt;/p&gt;&#xA;&lt;p&gt;此外，已有的运行中容器并没有崩溃，业务服务照常对外提供访问，只是任何&amp;quot;新建/重启容器&amp;quot;的动作全部失败；&lt;code&gt;docker images&lt;/code&gt; 列表里堆积了上百个 &lt;code&gt;&amp;lt;none&amp;gt;&lt;/code&gt; 的中间镜像，磁盘肉眼可见地越来越慢。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，我本能地按&amp;quot;磁盘满&amp;quot;的思路去查。执行 &lt;code&gt;df -h&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;Filesystem      Size  Used Avail Use% Mounted on&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/vda1        50G   32G   18G  63% /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;空间明明还剩 18G，所以 &amp;ldquo;no space left on device&amp;rdquo; 在这里是假象。结合经验，Linux 上除了字节数，还有另一个隐藏上限——&lt;strong&gt;inode 数量&lt;/strong&gt;。一个文件系统能创建的文件总数受 inode 限制，即使字节没满，inode 耗尽同样会报这个错。&lt;/p&gt;&#xA;&lt;p&gt;第二步，用 &lt;code&gt;df -i&lt;/code&gt; 验证猜测：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;Filesystem       Inodes   IUsed    IFree IUse% Mounted on&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/dev/vda1       &lt;span style=&#34;color:#ae81ff&#34;&gt;3276800&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3276790&lt;/span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;  100% /&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;果然，inode 使用率 100%，只剩 10 个可用。问题定性了：这是 inode 耗尽，不是磁盘空间耗尽。&lt;/p&gt;&#xA;&lt;p&gt;第三步，定位是哪个目录吃掉了 inode。因为 Docker 的根目录默认在 &lt;code&gt;/var/lib/docker&lt;/code&gt;，我写了个循环统计子目录的文件数：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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:#66d9ef&#34;&gt;for&lt;/span&gt; d in /var/lib/docker/*; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$d&lt;span style=&#34;color:#e6db74&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;find &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$d&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; -xdev -type f 2&amp;gt;/dev/null | wc -l&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&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;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;输出显示 &lt;code&gt;/var/lib/docker/overlay2&lt;/code&gt; 一个目录就占了 320 多万个文件，几乎吃光了全部 inode。overlay2 是 Docker 的存储驱动，每一层镜像、每个容器的可写层都被拆成一个个真实的小文件存放在这里。&lt;/p&gt;&#xA;&lt;p&gt;第四步，进一步分析 overlay2 内部构成。用 &lt;code&gt;docker system df&lt;/code&gt; 看到：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Images          214       12        28.4GB    26.1GB (91%)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Containers      187       3         1.2GB     1.1GB (95%)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Local Volumes   9         2         0         0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build Cache     0         0         0         0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;镜像和&amp;quot;僵尸容器&amp;quot;（已退出但未删除）数量惊人。再钻进 overlay2 看单目录文件数分布，发现大量 &lt;code&gt;&amp;lt;hash&amp;gt;/diff&lt;/code&gt; 目录每个都装着几万甚至十几万个小文件——这正是那些 Java/Maven 项目在构建时往容器可写层写入海量 &lt;code&gt;.class&lt;/code&gt;、依赖 jar、源码文件留下的痕迹。&lt;/p&gt;&#xA;&lt;p&gt;第五步，确认加剧因素——日志。检查 &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;，发现根本没有配置 json-file 的日志轮转（&lt;code&gt;max-size&lt;/code&gt; / &lt;code&gt;max-file&lt;/code&gt;）。这意味着每个容器的标准输出日志都在 &lt;code&gt;/var/lib/docker/containers/&amp;lt;id&amp;gt;/&amp;lt;id&amp;gt;-json.log&lt;/code&gt; 里无限增长，虽然单个日志是&amp;quot;大文件&amp;quot;对 inode 贡献不大，但叠加海量中间层小文件，最终把 inode 彻底打满。&lt;/p&gt;&#xA;&lt;p&gt;至此根因链条清晰：长期不清理 + 构建任务频繁创建容器/镜像 + 日志不轮转，导致 overlay2 累积了数百万个小文件，耗尽 inode，新容器再也无法创建目录。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;当务之急是腾出 inode，让 Docker 能继续工作：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;清理已退出容器与悬空镜像&lt;/strong&gt;（释放海量小文件）：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;docker container prune -f&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker image prune -a -f&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker system prune -a --volumes -f&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;执行后 &lt;code&gt;df -i&lt;/code&gt; 的 IFree 从 10 回升到 290 多万，inode 使用率降到 12%。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;重启 Docker 守护进程&lt;/strong&gt;让状态归一：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;systemctl restart docker&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;临时把 Docker 根目录迁到 inode 更充裕的磁盘&lt;/strong&gt;（可选，针对根盘 inode 本就偏小的云主机）：挂载一块数据盘，修改 &lt;code&gt;daemon.json&lt;/code&gt; 的 &lt;code&gt;&amp;quot;data-root&amp;quot;: &amp;quot;/data/docker&amp;quot;&lt;/code&gt; 后重启。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;验证&lt;/strong&gt;：手动 &lt;code&gt;docker run --rm hello-world&lt;/code&gt; 成功，Runner 流水线逐步恢复正常。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;表面看是&amp;quot;磁盘满了&amp;quot;，本质是&lt;strong&gt;文件系统 inode 资源被海量小文件耗尽&lt;/strong&gt;。overlay2 存储驱动把每个镜像层和容器可写层都映射成宿主机的真实文件，构建型任务（编译、打包）会在容器内产生大量细小文件，这些文件在容器退出后若不被清理，就以&amp;quot;僵尸容器 + dangling 镜像&amp;quot;的形式永久占用 inode。再加上日志未配置轮转，雪上加霜。云主机默认文件系统的 inode 总数往往偏小（本例仅 327 万），在 CI 场景下极容易被打满。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;配置日志轮转&lt;/strong&gt;：在 &lt;code&gt;daemon.json&lt;/code&gt; 中加入&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log-driver&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;json-file&amp;#34;&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;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;log-opts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;max-size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;100m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;max-file&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;3&amp;#34;&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;建立定期清理机制&lt;/strong&gt;：用 cron 每天凌晨执行 &lt;code&gt;docker system prune -a -f --filter &amp;quot;until=72h&amp;quot;&lt;/code&gt;，只保留近三天的资源。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;inode 监控告警&lt;/strong&gt;：把 &lt;code&gt;df -i&lt;/code&gt; 接入监控（Node Exporter + Prometheus 或云监控），inode 使用率超 80% 即告警，比磁盘空间告警更早发现隐患。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;构建阶段减少可写层文件&lt;/strong&gt;：CI 中尽量用多阶段构建（multi-stage build），把编译产生的中间文件留在构建阶段、不带入最终镜像；构建缓存挂载到宿主机独立大目录而非容器可写层。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;给 Docker 分配独立数据盘&lt;/strong&gt;：新建大 inode 文件系统（&lt;code&gt;mkfs.ext4 -i 8192&lt;/code&gt; 调高密度）专供 &lt;code&gt;/var/lib/docker&lt;/code&gt;，从容量上根除风险。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障给我最深的教训是：&lt;strong&gt;排查 &amp;ldquo;no space left on device&amp;rdquo; 不能只看 &lt;code&gt;df -h&lt;/code&gt;，一定要补一眼 &lt;code&gt;df -i&lt;/code&gt;&lt;/strong&gt;。在容器、CI、日志这类&amp;quot;产生海量小文件&amp;quot;的场景里，inode 耗尽比磁盘字节耗尽更常见、更隐蔽。把日志轮转、定期 prune、inode 监控三件事做成标准动作，基本可以杜绝这类问题再次发生。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>FortiGate 策略配错，内网 DNS 为何解析失败？</title>
            <link>https://blog.5772447.xyz/posts/66557bdd/</link>
            <pubDate>Fri, 15 Aug 2025 07:38:48 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/66557bdd/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;2026年5月中旬，公司新收购的一家分公司完成网络改造，核心交换机升级为华为S7706，出口防火墙替换为FortiGate 100F，由我负责整体网络运维支持。改造完成后前三天网络运行正常，但从第四天开始，陆续有员工反映&amp;quot;网页打开很慢&amp;quot;、&amp;ldquo;有些网站完全打不开&amp;rdquo;、&amp;ldquo;微信能发消息但图片加载很慢&amp;rdquo;。&lt;/p&gt;&#xA;&lt;p&gt;由于分公司没有专职网络工程师，问题上报到总部后由我远程协助排查。初期怀疑是ISP链路问题，联系运营商测速后确认出口带宽正常，100M专线上下行均达标，问题指向内网。&lt;/p&gt;&#xA;&lt;p&gt;影响范围逐渐扩大，到第二天已有约40%的员工反映网络异常，部分关键业务系统（如ERP、OA）访问也出现间歇性超时，情况比较紧急。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;通过远程桌面连接到分公司的一台运维跳板机，我进行了以下几项基础测试，汇总故障现象如下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;1. 网络连通性测试&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;ping 8.8.8.8&lt;/code&gt; 通，延迟约12ms，无丢包；&lt;code&gt;ping www.baidu.com&lt;/code&gt; 间歇性超时，大约30%的ICMP包被丢弃，且延迟波动极大（12ms~3000ms）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;2. DNS解析测试&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;使用 &lt;code&gt;nslookup&lt;/code&gt; 测试内网DNS服务器（由AD域控兼做DNS，IP为192.168.10.10）：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;C:\&amp;gt; nslookup www.baidu.com 192.168.10.10&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DNS request timed out.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timeout was 2 seconds.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DNS request timed out.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timeout was 2 seconds.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;多次尝试后偶尔能解析成功，但响应时间普遍超过5秒。换成公共DNS（114.114.114.114）测试，现象一致。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;3. HTTP/HTTPS访问测试&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;用curl测试HTTP访问：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;C:\&amp;gt; curl -w &amp;#34;%{time_total}\n&amp;#34; -o /dev/null -s http://www.baidu.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;5.237&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;首次访问耗时超过5秒，后续复用连接后有所改善，但刷新页面后问题复现。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;4. 关键观察&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;有一个重要现象：使用IP地址直接访问的业务系统（如 &lt;code&gt;http://10.10.1.20&lt;/code&gt;）完全正常，延迟稳定；而使用域名访问的系统（如 &lt;code&gt;http://oa.company.com&lt;/code&gt;）则间歇性超时。这进一步将问题范围缩小到DNS解析环节。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;h3 id=&#34;第一步确认dns服务器本身是否正常&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e7%a1%ae%e8%ae%a4dns%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%9c%ac%e8%ba%ab%e6%98%af%e5%90%a6%e6%ad%a3%e5%b8%b8&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第一步：确认DNS服务器本身是否正常&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;首先排除DNS服务器（AD域控）自身故障的可能性。远程登录到域控服务器，检查DNS服务状态：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PS&amp;gt; Get-Service DNS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Status   Name   DisplayName&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Running  DNS    DNS Server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;DNS服务运行正常。进一步检查DNS日志，发现大量&amp;quot;Event ID 4013&amp;quot;和&amp;quot;Event ID 3150&amp;quot;的警告日志，提示&amp;quot;DNS服务器无法解析外部域名，转发器超时&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;查看DNS转发器配置，发现配置了四个转发器：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;202.96.128.86（本地运营商DNS）&lt;/li&gt;&#xA;&lt;li&gt;114.114.114.114&lt;/li&gt;&#xA;&lt;li&gt;8.8.8.8&lt;/li&gt;&#xA;&lt;li&gt;8.8.4.4&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;看起来配置没有问题，但为什么解析会超时？&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步抓包分析dns流量&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e6%8a%93%e5%8c%85%e5%88%86%e6%9e%90dns%e6%b5%81%e9%87%8f&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第二步：抓包分析DNS流量&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在域控服务器上启动Wireshark，过滤DNS流量（UDP 53端口），然后进行解析测试：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;C:\&amp;gt; nslookup www.google.com 192.168.10.10&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;抓包结果发现了关键线索：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;域控向外网转发DNS查询时，发出的UDP包目标端口53，但&lt;strong&gt;完全没有收到响应包&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;域控随后尝试TCP 53重试，同样没有响应&lt;/li&gt;&#xA;&lt;li&gt;整个过程中，域控本身可以ping通所有转发器IP，网络层是通的&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这说明&lt;strong&gt;DNS查询包在出去的路上被丢了&lt;/strong&gt;，而不是DNS服务器本身的问题。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步检查fortigate防火墙策略&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%b8%89%e6%ad%a5%e6%a3%80%e6%9f%a5fortigate%e9%98%b2%e7%81%ab%e5%a2%99%e7%ad%96%e7%95%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第三步：检查FortiGate防火墙策略&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;分公司新上线的FortiGate 100F是本次网络改造的新增设备，重点怀疑对象。通过FortiCloud远程登录FortiGate管理界面，检查防火墙策略。&lt;/p&gt;&#xA;&lt;p&gt;FortiGate的策略配置相对复杂，新上线时由实施工程师配置，我之前只做了基础验收测试。逐条检查策略，发现了一条当时为&amp;quot;临时测试&amp;quot;创建的策略，规则如下：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Policy ID: 5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Name: DNS_OUT_TEST&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Source: all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Destination: all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Service: DNS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Action: DENY&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Schedule: always&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Log: disable&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;这条策略的意图是&amp;quot;临时禁止某个测试用的DNS流量&amp;quot;，但配置时&lt;strong&gt;Source设成了all&lt;/strong&gt;，导致所有出站DNS流量（UDP/TCP 53）都被这条策略匹配并丢弃了。&lt;/p&gt;&#xA;&lt;p&gt;更糟糕的是，这条DENY策略的&lt;strong&gt;序列号是5&lt;/strong&gt;，排在所有ALLOW策略之前（FortiGate策略是自上而下匹配的）。也就是说，任何出站DNS流量在到达后面的ALLOW策略之前，先被这条策略拦截了。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第四步验证猜测&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e5%9b%9b%e6%ad%a5%e9%aa%8c%e8%af%81%e7%8c%9c%e6%b5%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第四步：验证猜测&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;为了验证是不是这条策略的问题，我先记录当前策略配置，然后临时禁用Policy ID 5，再进行DNS解析测试：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;C:\&amp;gt; nslookup www.baidu.com 192.168.10.10&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Server:  dc01.company.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Address:  192.168.10.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;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Non-authoritative answer:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Name:    www.a.shifen.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Addresses:  110.242.68.4&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            110.242.68.3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Aliases:  www.baidu.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;解析成功，响应时间不到100ms！进一步测试网页访问、业务系统访问，全部恢复正常。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第五步追溯策略来源&#34;&gt;&lt;a href=&#34;#%e7%ac%ac%e4%ba%94%e6%ad%a5%e8%bf%bd%e6%ba%af%e7%ad%96%e7%95%a5%e6%9d%a5%e6%ba%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;第五步：追溯策略来源&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;联系当时负责实施的工程师，了解到这条策略是他做DNS代理测试时创建的，测试完后忘记删除了。由于FortiGate的策略匹配是顺序制的，这条DENY策略插在策略列表靠前的位置，导致所有DNS出站流量被静默丢弃。&lt;/p&gt;&#xA;&lt;p&gt;之所以前三天没有暴露问题，是因为当时客户端DNS缓存尚未过期，且部分员工使用的是浏览器内置的DNS over HTTPS（DoH），绕过了系统DNS设置，所以问题有延迟才集中爆发。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;问题的根因已经明确，解决步骤如下：&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-删除错误的测试策略&#34;&gt;&lt;a href=&#34;#1-%e5%88%a0%e9%99%a4%e9%94%99%e8%af%af%e7%9a%84%e6%b5%8b%e8%af%95%e7%ad%96%e7%95%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 删除错误的测试策略&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;登录FortiGate，删除Policy ID 5：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config firewall policy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    delete 5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;end&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;2-优化dns流量策略&#34;&gt;&lt;a href=&#34;#2-%e4%bc%98%e5%8c%96dns%e6%b5%81%e9%87%8f%e7%ad%96%e7%95%a5&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 优化DNS流量策略&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;原来策略列表中，DNS出站流量依赖一条&amp;quot;any to any&amp;quot;的通用放行策略，不够精细。新建专用策略，明确允许内网DNS出站：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config firewall policy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    edit 0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set name &amp;#34;DNS_OUTBOUND&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set srcintf &amp;#34;internal&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set dstintf &amp;#34;wan1&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set srcaddr &amp;#34;RFC1918&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set dstaddr &amp;#34;all&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set action accept&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set schedule &amp;#34;always&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set service &amp;#34;DNS&amp;#34; &amp;#34;DNS-TCP&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set logtraffic all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;end&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;关键点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;明确指定了源接口（internal）和目的接口（wan1）&lt;/li&gt;&#xA;&lt;li&gt;服务明确限定为DNS（UDP 53）和DNS-TCP（TCP 53）&lt;/li&gt;&#xA;&lt;li&gt;开启全量日志，便于后续排查&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3-优化dns服务器转发器配置&#34;&gt;&lt;a href=&#34;#3-%e4%bc%98%e5%8c%96dns%e6%9c%8d%e5%8a%a1%e5%99%a8%e8%bd%ac%e5%8f%91%e5%99%a8%e9%85%8d%e7%bd%ae&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 优化DNS服务器转发器配置&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;原先DNS转发器配置了四个，其中8.8.8.8和8.8.4.4从分公司网络访问延迟较高（分公司出口是电信专线，访问Google DNS需要绕路）。优化后的转发器列表：&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;优先级&lt;/th&gt;&#xA;          &lt;th&gt;DNS服务器&lt;/th&gt;&#xA;          &lt;th&gt;说明&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1&lt;/td&gt;&#xA;          &lt;td&gt;202.96.128.86&lt;/td&gt;&#xA;          &lt;td&gt;本地电信DNS，延迟最低&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;2&lt;/td&gt;&#xA;          &lt;td&gt;114.114.114.114&lt;/td&gt;&#xA;          &lt;td&gt;国内公共DNS，备用&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;3&lt;/td&gt;&#xA;          &lt;td&gt;内网根提示&lt;/td&gt;&#xA;          &lt;td&gt;直接迭代查询，最后兜底&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h3 id=&#34;4-在fortigate上启用dns过滤的安全功能&#34;&gt;&lt;a href=&#34;#4-%e5%9c%a8fortigate%e4%b8%8a%e5%90%af%e7%94%a8dns%e8%bf%87%e6%bb%a4%e7%9a%84%e5%ae%89%e5%85%a8%e5%8a%9f%e8%83%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 在FortiGate上启用DNS过滤的安全功能&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;FortiGate有内置的DNS过滤功能，可以阻断恶意域名解析。在优化后的策略上启用了此功能：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config firewall policy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    edit 10&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set dnsfilter-profile &amp;#34;default&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;end&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;本次故障的根本原因是&lt;strong&gt;FortiGate防火墙策略配置错误&lt;/strong&gt;，具体可以拆解为以下几个层面：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;直接原因&lt;/strong&gt;：一条Source为&amp;quot;all&amp;quot;的DNS DENY策略被错误地保留在策略列表中，且序列号靠前，导致所有出站DNS流量被静默丢弃。&lt;/p&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;策略审查缺失&lt;/strong&gt;：新设备上线的策略清单没有经过严格的Code Review式审查，测试策略未及时清理&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;缺乏策略变更管理&lt;/strong&gt;：FortiGate策略的增删改没有走变更流程，实施工程师可以随意添加策略&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;监控覆盖不足&lt;/strong&gt;：FortiGate的DNS流量被DENY的日志没有开启（原策略Log设置为disable），导致无法通过日志快速发现问题&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;DNS解析超时表现不直观&lt;/strong&gt;：客户端DNS解析超时后会有重试，ICMP ping通但HTTP慢，这种&amp;quot;半通不通&amp;quot;的现象容易引导排查方向偏离&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;针对本次故障暴露的问题，制定了以下预防措施：&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-建立防火墙策略变更管理流程&#34;&gt;&lt;a href=&#34;#1-%e5%bb%ba%e7%ab%8b%e9%98%b2%e7%81%ab%e5%a2%99%e7%ad%96%e7%95%a5%e5%8f%98%e6%9b%b4%e7%ae%a1%e7%90%86%e6%b5%81%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;1. 建立防火墙策略变更管理流程&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;所有FortiGate策略变更必须满足：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;变更前填写《防火墙策略变更申请表》，注明策略用途、源目地址、服务端口、有效期&lt;/li&gt;&#xA;&lt;li&gt;测试策略必须设置明确的有效期（通过FortiGate的&lt;code&gt;schedule&lt;/code&gt;功能实现自动过期）&lt;/li&gt;&#xA;&lt;li&gt;变更后由第二人复核策略列表&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2-启用关键策略的日志功能&#34;&gt;&lt;a href=&#34;#2-%e5%90%af%e7%94%a8%e5%85%b3%e9%94%ae%e7%ad%96%e7%95%a5%e7%9a%84%e6%97%a5%e5%bf%97%e5%8a%9f%e8%83%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;2. 启用关键策略的日志功能&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;所有DENY类策略必须开启日志（&lt;code&gt;set logtraffic all&lt;/code&gt;），以便在日志中心（FortiAnalyzer或FortiCloud）中监控被拦截的流量，快速发现问题。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3-部署网络监控告警&#34;&gt;&lt;a href=&#34;#3-%e9%83%a8%e7%bd%b2%e7%bd%91%e7%bb%9c%e7%9b%91%e6%8e%a7%e5%91%8a%e8%ad%a6&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;3. 部署网络监控告警&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;在监控系统中增加以下告警项：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;DNS解析成功率低于95%时告警&lt;/li&gt;&#xA;&lt;li&gt;FortiGate策略命中次数异常（如某条DENY策略突然有大量命中）时告警&lt;/li&gt;&#xA;&lt;li&gt;内网到外网DNS服务器的延迟超过100ms时告警&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;具体实现可以用Prometheus + Blackbox Exporter做DNS探测，告警推送到企业微信。&lt;/p&gt;&#xA;&lt;h3 id=&#34;4-标准化新设备上线检查清单&#34;&gt;&lt;a href=&#34;#4-%e6%a0%87%e5%87%86%e5%8c%96%e6%96%b0%e8%ae%be%e5%a4%87%e4%b8%8a%e7%ba%bf%e6%a3%80%e6%9f%a5%e6%b8%85%e5%8d%95&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;4. 标准化新设备上线检查清单&#xD;&#xA;&lt;/h3&gt;&lt;p&gt;制作了《FortiGate上线检查清单》，包含以下关键检查项：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 所有测试策略已清理或设置过期时间&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 策略序列号经过合理性审查（宽策略在前，窄策略在后）&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; DENY策略均开启日志&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; DNS、NTP等关键基础服务的策略已明确配置&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 保存配置（&lt;code&gt;execute backup&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这是一次典型的&amp;quot;配置残留&amp;quot;引发的网络故障。FortiGate作为状态检测防火墙，策略匹配顺序是自上而下，一条配置不当的DENY策略所产生的破坏力，不亚于一次DDoS攻击。&lt;/p&gt;&#xA;&lt;p&gt;几个值得记取的教训：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;测试策略必须有过期机制&lt;/strong&gt;。FortiGate支持&lt;code&gt;schedule&lt;/code&gt;设置策略有效期，所有临时测试策略都应该用这个功能，而不是依赖&amp;quot;记得删除&amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;DNS是网络的基础中的基础&lt;/strong&gt;。DNS出问题时的表现非常具有迷惑性——ping IP通但域名不通，很容易被误判为应用层问题&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;抓包是最直接的排查手段&lt;/strong&gt;。在本次故障中，Wireshark抓包看到的&amp;quot;有去无回&amp;quot;现象，是锁定问题方向的关键&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;策略变更要有审计&lt;/strong&gt;。FortiGate的&lt;code&gt;config revision&lt;/code&gt;功能可以定期自动备份配置，建议开启&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;网络运维工作中，&amp;ldquo;最小化变更影响&amp;quot;和&amp;quot;可回溯性&amp;quot;是两个核心原则。这次故障如果配置备份和策略审计做到位，本可以在5分钟内定位问题，而不需要花费近2个小时逐步排查。&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;em&gt;本文所有IP地址、域名均已脱敏处理，技术细节基于真实案例整理。&lt;/em&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>Nginx 限流误杀正常请求：阈值调优与复盘</title>
            <link>https://blog.5772447.xyz/posts/8abd0b2a/</link>
            <pubDate>Sun, 23 Nov 2025 22:51:12 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/8abd0b2a/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们的主站 &lt;code&gt;www.example.com&lt;/code&gt; 使用 Nginx 1.24 作为七层接入网关，前面是 CDN，后面挂 8 个应用节点。由于此前遭遇过一次恶性 CC 攻击，安全团队要求对核心接口加限流。目标是：拦住异常高频的刷接口行为，但&lt;strong&gt;不能影响正常用户的浏览和下单&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;限流方案采用 Nginx 原生的 &lt;code&gt;limit_req&lt;/code&gt; 模块（基于漏桶算法），按客户端 IP 做粒度。上线时间是周一下午，由运维在网关配置中新增了一段 &lt;code&gt;limit_req_zone&lt;/code&gt; + &lt;code&gt;limit_req&lt;/code&gt; 规则，并 &lt;code&gt;nginx -s reload&lt;/code&gt; 平滑生效。本以为只是&amp;quot;加一道保险&amp;quot;，没想到立刻引发客诉。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;reload 后大约 10 分钟，客服群开始炸：大量用户反馈&amp;quot;页面打开就提示 503 Service Temporarily Unavailable&amp;quot;，且&lt;strong&gt;不是刷子，是普通用户&lt;/strong&gt;，包括公司内网同事自己访问也中招。&lt;/p&gt;&#xA;&lt;p&gt;监控侧：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Nginx &lt;code&gt;503&lt;/code&gt; 返回码占比从 0.1% 飙到 18%；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;limit_req&lt;/code&gt; 拒绝计数（&lt;code&gt;$limit_req_status&lt;/code&gt;）持续高位：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;limit_req_status  rejected: 12453  (last 1 min)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;被拒的 IP 高度分散，并非集中在少数异常 IP，说明是&lt;strong&gt;正常流量被误杀&lt;/strong&gt;；&lt;/li&gt;&#xA;&lt;li&gt;应用节点 CPU、连接数都很低，证明后端完全健康，问题 100% 出在网关限流层。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这与&amp;quot;防 CC&amp;quot;的目标完全背离：攻击没拦住多少，正常用户先被砍了一半。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，定位是哪条 limit_req 规则在拒绝。打开 Nginx 的 &lt;code&gt;limit_req_status&lt;/code&gt; 日志字段，确认返回 503 的请求都带 &lt;code&gt;limit_req_status=503&lt;/code&gt;，且命中的 zone 是 &lt;code&gt;perip&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;第二步，看配置。问题一目了然：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;http&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;limit_req_zone&lt;/span&gt; $binary_remote_addr &lt;span style=&#34;color:#e6db74&#34;&gt;zone=perip:10m&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;rate=2r/s&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;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;location&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#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;limit_req&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;zone=perip&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;burst=3&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;nodelay&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;http://backend&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;三个致命点：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;rate=2r/s&lt;/code&gt; 太小&lt;/strong&gt;：每个 IP 平均每秒只允许 2 个请求。现代网页一次打开就并发数十个请求（html + css + js + 图片 + api），瞬时远超 2/s。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;burst=3&lt;/code&gt; 太小&lt;/strong&gt;：只缓冲 3 个超出请求就拒绝，正常用户的突发并发根本装不下。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;nodelay&lt;/code&gt; 误用&lt;/strong&gt;：&lt;code&gt;nodelay&lt;/code&gt; 让 burst 内的请求不排队立即处理，等于把限流瞬时阈值直接抬到 &lt;code&gt;rate+burst=5&lt;/code&gt;，超出立刻 503，没有平滑过渡，正常用户的并发瞬间被打挂。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;第三步，验证判断。用正常浏览器行为模拟单 IP 的首屏请求数：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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 -s -o /dev/null -w &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%{http_code}\n&amp;#34;&lt;/span&gt; https://www.example.com/&#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;200&lt;/span&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;# 并发模拟首屏 20 个资源请求&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ seq &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; | xargs -P &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; -I&lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; curl -s -o /dev/null -w &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%{http_code}\n&amp;#34;&lt;/span&gt; https://www.example.com/assets/&lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; 2&amp;gt;/dev/null | sort | uniq -c&#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;17&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;503&lt;/span&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;3&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;单 IP 并发 20 个请求，17 个被 503——完美复现用户&amp;quot;打开就报错&amp;quot;。这正是 &lt;code&gt;rate+burst=5&lt;/code&gt; 在 &lt;code&gt;nodelay&lt;/code&gt; 下的直接后果。&lt;/p&gt;&#xA;&lt;p&gt;第四步，确认 CDN 是否放大问题。由于前面是 CDN，回源到 Nginx 时客户端 IP 已被 &lt;code&gt;X-Forwarded-For&lt;/code&gt; 携带，但 &lt;code&gt;limit_req_zone&lt;/code&gt; 用的是 &lt;code&gt;$binary_remote_addr&lt;/code&gt;（即 CDN 边缘节点 IP）。这意味着&lt;strong&gt;所有经同一 CDN 节点回源的用户被当成同一个 IP 限流&lt;/strong&gt;，进一步把正常流量成片误杀。这是第二个隐藏坑。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;应急先回退，再给出正确配置：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;立即 &lt;code&gt;nginx -s reload&lt;/code&gt; 回退到无 limit_req 的版本，503 比例 1 分钟内归零，客诉停止。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;修正限流参数，按&amp;quot;正常用户首屏并发约 20~30 个请求、且允许一定突发&amp;quot;来设计：&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;http&lt;/span&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;# 用真实客户端 IP（CDN 场景取 XFF 最左）&#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:#f92672&#34;&gt;map&lt;/span&gt; $http_x_forwarded_for $client_real_ip {&#xA;&lt;/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&lt;/span&gt; $binary_remote_addr;&#xA;&lt;/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;#34;~^(?P&amp;lt;first&amp;gt;\d+\.\d+\.\d+\.\d+)&amp;#34;&lt;/span&gt; $first;&#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;limit_req_zone&lt;/span&gt; $client_real_ip &lt;span style=&#34;color:#e6db74&#34;&gt;zone=perip:20m&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;rate=20r/s&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;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;location&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#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;limit_req&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;zone=perip&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;burst=40&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;delay=20&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;limit_req_status&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;429&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;http://backend&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;要点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;rate=20r/s&lt;/code&gt; 容纳正常浏览；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;burst=40&lt;/code&gt; 给足突发缓冲；&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;去掉 &lt;code&gt;nodelay&lt;/code&gt;&lt;/strong&gt;，改用 &lt;code&gt;delay=20&lt;/code&gt;：前 20 个超出的请求不延迟，其余进队列平滑处理，既保体验又防刷；&lt;/li&gt;&#xA;&lt;li&gt;限流拒绝码改为 &lt;code&gt;429&lt;/code&gt;（语义更准确），并基于 &lt;code&gt;X-Forwarded-For&lt;/code&gt; 取真实客户端 IP，避免 CDN 合并误杀。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;对静态资源（/assets/、图片）&lt;strong&gt;不限流&lt;/strong&gt;，只对 API 和登录等敏感路径限流，进一步降低误杀面。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;灰度上线后观察 30 分钟：503/429 比例稳定在 0.3%，且被拒 IP 确为少数高频异常来源，正常用户零投诉。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是 &lt;strong&gt;&lt;code&gt;limit_req&lt;/code&gt; 阈值设计与实际流量模型严重错配&lt;/strong&gt;，叠加两个误用：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;rate&lt;/code&gt;/&lt;code&gt;burst&lt;/code&gt; 按&amp;quot;单请求流&amp;quot;想象设置（2r/s、burst 3），但浏览器首屏天然并发几十请求，正常行为就被判为&amp;quot;超限&amp;quot;；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;nodelay&lt;/code&gt; 把漏桶本该的&amp;quot;平滑排队&amp;quot;变成&amp;quot;瞬间砍杀&amp;quot;，剥夺了缓冲；&lt;/li&gt;&#xA;&lt;li&gt;CDN 场景下用 &lt;code&gt;$binary_remote_addr&lt;/code&gt; 取到的是 CDN 节点 IP，等于把整片用户合并成一个被限流对象，放大误杀。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;本质上，限流是保护手段，但阈值必须建立在&lt;strong&gt;对正常用户行为基线的量化&lt;/strong&gt;之上，不能拍脑袋。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;先度量，再限流&lt;/strong&gt;：上线前用日志统计真实用户 P95/P99 的每 IP 请求速率与并发，阈值取正常峰值的 1.5~2 倍。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;慎用 &lt;code&gt;nodelay&lt;/code&gt;&lt;/strong&gt;：除非明确要&amp;quot;超 burst 立即拒绝&amp;quot;，否则用 &lt;code&gt;delay=&lt;/code&gt; 让超出请求排队，保住体验。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;CDN 后取真实 IP&lt;/strong&gt;：务必 &lt;code&gt;real_ip&lt;/code&gt; / &lt;code&gt;X-Forwarded-For&lt;/code&gt; 解析真实客户端地址，避免按边缘节点聚合限流。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;分级限流&lt;/strong&gt;：静态资源不限，敏感/写接口严限，做到&amp;quot;该拦的拦、该放的放&amp;quot;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;灰度 + 监控&lt;/strong&gt;：新限流规则先 1 台网关灰度，盯 &lt;code&gt;limit_req_status&lt;/code&gt; 与 4xx 比例，确认无误再全量；拒绝码用 429 便于区分。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;返回友好提示&lt;/strong&gt;：对限流返回 429 + &lt;code&gt;Retry-After&lt;/code&gt; 头，前端做退避重试，避免用户看到生硬 503。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障是典型的&amp;quot;安全策略反噬业务&amp;quot;。&lt;code&gt;limit_req&lt;/code&gt; 本身没错，错在阈值是凭直觉设的、且 &lt;code&gt;nodelay&lt;/code&gt; 用错了地方。排查关键三步：&lt;code&gt;limit_req_status&lt;/code&gt; 日志确认拒绝来源 → 看 &lt;code&gt;rate/burst/nodelay&lt;/code&gt; 组合 → 用真实并发复现 503。记住三条铁律：限流阈值必须基于真实流量基线；&lt;code&gt;nodelay&lt;/code&gt; 不是默认选项；CDN 后面一定要还原真实客户端 IP。限流的目标是&amp;quot;拦坏人&amp;quot;，不是&amp;quot;误伤好人&amp;quot;，上线前做一次灰度观测，能省掉一次客诉危机。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>MPLS 专线抖动致跨机房数据库同步中断的定位</title>
            <link>https://blog.5772447.xyz/posts/30de78ed/</link>
            <pubDate>Thu, 09 Oct 2025 12:09:19 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/30de78ed/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们的核心交易库采用&amp;quot;主机房 A + 备机房 B&amp;quot;跨机房主从架构：A 机房为主（读写），B 机房为从（只读报表/容灾），通过 MySQL 原生的主从复制（基于 binlog 的异步复制）跨机房同步。A、B 两机房之间走一条运营商 MPLS 专线（专线网关为 A 侧 &lt;code&gt;10.0.0.1&lt;/code&gt;、B 侧 &lt;code&gt;10.0.0.2&lt;/code&gt;，互联地址段 &lt;code&gt;10.0.0.0/30&lt;/code&gt;），业务读写分离由中间件按&amp;quot;主写从读&amp;quot;路由。&lt;/p&gt;&#xA;&lt;p&gt;2025 年 10 月 9 日上午，报表团队反馈 B 机房查到的数据与 A 机房对不上，随后复制监控告警。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;10:30 起，B 机房从库 &lt;code&gt;Slave_IO_Running&lt;/code&gt; 变为 &lt;code&gt;No&lt;/code&gt;，复制线程中断；&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Seconds_Behind_Master&lt;/code&gt; 在中断前一度飙到 120s 以上，随后线程挂掉；&lt;/li&gt;&#xA;&lt;li&gt;业务侧读写分离出现数据不一致：用户在 A 机房刚下的单，在 B 机房报表里查不到；&lt;/li&gt;&#xA;&lt;li&gt;从库错误日志反复出现连接主库超时、重试失败：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[ERROR] Slave I/O: error connecting to master &amp;#39;repl@10.0.0.1:3306&amp;#39; - retry-time: 60 retries: 86400, Error_code: 2013 (Lost connection to server during query)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[ERROR] Slave I/O: Got timeout reading communication packets&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;5&#34;&gt;&#xA;&lt;li&gt;但 A 机房主库本身健康，本地读写无异常；B 机房到公网、到其他内网段正常，唯独到 A 机房专线时好时坏。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步：确认是网络问题还是数据库问题。&lt;/strong&gt; 在 B 机房从库机器上对主库 IP 做连续 ping 与 mtr：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;ping -c &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; 10.0.0.1&#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;# 64 bytes from 10.0.0.1: icmp_seq=12 ttl=63 time=1823 ms&lt;/span&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;# 64 bytes from 10.0.0.1: icmp_seq=13 ttl=63 time=*  (丢包)&lt;/span&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;# --- 10.0.0.1 ping statistics --- 20 packets transmitted, 15 received, 25% packet loss&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;平时该专线 RTT 在 3–5ms，此刻已到 1.8s 且 25% 丢包，明显是专线质量劣化。再看 mtr 路径：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;mtr -r -c &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; 10.0.0.1&#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;# Host   Loss%  Snt  Avg  StDev&lt;/span&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;# 10.0.0.2  0.0%  30   0.4  0.2   (B 侧网关正常)&lt;/span&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;# 10.0.0.1 25.0%  30 1823  900    (A 侧网关抖动)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;抖动发生在跨机房 MPLS 这一段，而非本地。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第二步：确认抖动特征。&lt;/strong&gt; 持续 5 分钟抓 RTT 分布，发现是周期性突发：每约 40 秒出现一次 1–2 秒的时延尖峰并伴随丢包，低谷期又恢复正常。这种&amp;quot;规律性抖动&amp;quot;典型是运营商侧 MPLS 链路做了某种重路由或存在微突发拥塞。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步：核对带宽与 QoS。&lt;/strong&gt; 登录两侧专线网关查接口统计：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;show interfaces TenGigE0/0/0/1&#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;# input rate 8.2 Gbps, output rate 7.9 Gbps (专线带宽 10G)&lt;/span&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;# 输错: input errors 0, CRC 0, but &amp;#34;input drops&amp;#34; 累计上涨&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;show policy-map interface TenGigE0/0/0/1 output | inc drop&#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;#  class-default:  drop 18423 packets  (QoS 默认类丢包)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;发现默认类有持续丢包，说明瞬时流量逼近 10G 带宽上限，突发时被丢弃——这也解释了复制线程在大数据事务（如批量报表回放）时被卡断。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第四步：关联变更。&lt;/strong&gt; 联系运营商后确认，10:25 其对该 MPLS 链路做了一次保护倒换演练（未提前充分通知），部分流量被临时切到备用 LSP，路径变长、Buffer 不足，导致微突发丢包。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;先恢复复制&lt;/strong&gt;：在 B 机房从库手动重启复制线程，并临时调大复制相关超时，避免瞬时抖动再次秒断：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;STOP SLAVE;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHANGE MASTER &lt;span style=&#34;color:#66d9ef&#34;&gt;TO&lt;/span&gt; MASTER_CONNECT_RETRY&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, MASTER_RETRY_COUNT&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;86400&lt;/span&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;START&lt;/span&gt; SLAVE;&#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;-- 同时调大从库 net_read_timeout / net_write_timeout&#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:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;GLOBAL&lt;/span&gt; net_read_timeout&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;120&lt;/span&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;SET&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;GLOBAL&lt;/span&gt; net_write_timeout&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;120&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&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;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;-- 主库&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CHANGE MASTER &lt;span style=&#34;color:#66d9ef&#34;&gt;TO&lt;/span&gt; MASTER_HEARTBEAT_PERIOD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;网络层临时规避&lt;/strong&gt;：与运营商确认保护倒换演练窗口，将其避开业务高峰；同时对关键复制流量打 MPLS EXP/QoS 高优先级标签，避免被默认类丢弃。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;带宽扩容评估&lt;/strong&gt;：将专线从 10G 临时升级保障，错峰跑批量报表，降低瞬时拥塞。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;恢复后 &lt;code&gt;Seconds_Behind_Master&lt;/code&gt; 从 120s 逐步回落到 0，数据一致性在约 15 分钟后追平。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;跨机房 MPLS 专线出现周期性抖动+微突发丢包，击穿了异步复制链路的健壮性&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;运营商保护倒换演练使部分流量临时走绕路 LSP，路径 RTT 从 3ms 涨到 1.8s，Buffer 不足引发丢包；&lt;/li&gt;&#xA;&lt;li&gt;MySQL 异步复制的 IO 线程对网络中断敏感，默认 &lt;code&gt;net_read_timeout&lt;/code&gt; 较短，丢包导致 binlog 拉取中断即报错退出；&lt;/li&gt;&#xA;&lt;li&gt;复制线程挂掉后，写入仍在 A 机房进行，B 机房数据持续滞后，读写分离架构下用户读到陈旧数据；&lt;/li&gt;&#xA;&lt;li&gt;专线接口默认类 QoS 在带宽逼近上限时丢弃复制包，没有为数据库复制流量预留高优先级通道。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;本质是跨机房强一致依赖（复制）跑在一条&amp;quot;无 QoS 保障、又会发生抖动&amp;quot;的单链路上，缺乏超时容错与流量分级。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;复制参数加固&lt;/strong&gt;：从库设置合理的 &lt;code&gt;MASTER_CONNECT_RETRY&lt;/code&gt;、&lt;code&gt;net_read_timeout&lt;/code&gt;/&lt;code&gt;net_write_timeout&lt;/code&gt;，并开启 &lt;code&gt;MASTER_HEARTBEAT_PERIOD&lt;/code&gt;，让抖动后能快速自愈而非长期挂死。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;专线 QoS 分级&lt;/strong&gt;：为数据库复制、存储同步等跨机房关键流量打高优先级 MPLS EXP 标签，保证其在拥塞时不被默认类丢弃。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;双专线/多路径&lt;/strong&gt;：关键机房间部署主备两条异构运营商专线，配合 BFD 快速检测 + 动态路由切换，单链路抖动自动切备用。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;变更协同机制&lt;/strong&gt;：要求运营商任何 MPLS 倒换、演练必须提前通知并避开业务高峰，纳入变更窗口管理。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;一致性校验与告警&lt;/strong&gt;：部署 pt-table-checksum 定期比对主从差异；对 &lt;code&gt;Slave_IO_Running=No&lt;/code&gt;、&lt;code&gt;Seconds_Behind_Master&lt;/code&gt; 超阈值做秒级告警，避免滞后被业务先发现。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;读写分离降级&lt;/strong&gt;：当检测到从库延迟过大时，中间件自动把读请求切回主库，牺牲部分性能换取一致性。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障是典型的&amp;quot;网络抖动用数据一致性买单&amp;quot;：一条 MPLS 专线的保护倒换演练，通过 MySQL 异步复制的脆弱连接，传导成了跨机房数据不一致。&lt;/p&gt;&#xA;&lt;p&gt;排查路径很清晰——&lt;strong&gt;从库复制报错 → 网络层对照 ping/mtr 定位专线抖动 → 网关接口统计确认 QoS 丢包 → 关联运营商变更&lt;/strong&gt;，一线工程师只要按顺序下钻就能锁定。更深的启示是：跨机房复制这类&amp;quot;看似数据库、实则强依赖网络&amp;quot;的链路，必须在网络侧做 QoS 分级、多路径容灾，在数据库侧做超时与心跳加固，双管齐下才能扛住底层链路的日常抖动。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>记一次 K8s Pod OOMKilled 触发的服务雪崩</title>
            <link>https://blog.5772447.xyz/posts/b1ca8efe/</link>
            <pubDate>Wed, 02 Jul 2025 09:08:48 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/b1ca8efe/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们的订单中心 &lt;code&gt;order-service&lt;/code&gt; 跑在 Kubernetes 集群（v1.27，containerd 运行时）上，Deployment 配置 6 个副本，平时负载稳定，内存常驻约 600MB。该服务是交易链路的核心，下游由支付、库存等服务调用，上游又被 API 网关和多个内部业务系统依赖。&lt;/p&gt;&#xA;&lt;p&gt;某天上午，运营临时做了一个营销活动，订单量较平日上涨约 3 倍。活动开始约 20 分钟后，订单成功率告警触发。此时我们并未发版，纯属流量驱动的突发故障。集群节点规格为 8C16G，节点本身剩余内存充足，看起来不像是节点级资源问题。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;监控面板在 09:05 左右集中飘红：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;order-service&lt;/code&gt; 的 &lt;code&gt;CrashLoopBackOff&lt;/code&gt; 副本数从 0 涨到 4，6 个副本里一度只剩 2 个在 &lt;code&gt;Running&lt;/code&gt;；&lt;/li&gt;&#xA;&lt;li&gt;上游 API 网关大量返回 504，&lt;code&gt;order-service&lt;/code&gt; 调用超时率从 0.2% 升到 35%；&lt;/li&gt;&#xA;&lt;li&gt;订单创建成功率从 99.6% 跌到 58%，部分用户出现重复下单；&lt;/li&gt;&#xA;&lt;li&gt;滚动更新状态卡在 &lt;code&gt;Progressing&lt;/code&gt;：新副本 &lt;code&gt;ready&lt;/code&gt; 数量始终达不到 &lt;code&gt;minAvailable&lt;/code&gt;，Deployment 既不成功也不回滚。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;最迷惑的是：节点 &lt;code&gt;kubectl top node&lt;/code&gt; 显示内存还有 6G+ 空闲，但 Pod 就是不断重启。这说明问题出在 &lt;strong&gt;Pod 级别内存限制（limit）&lt;/strong&gt;，而不是节点容量。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，看 Pod 事件，直接命中关键字：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ kubectl describe pod order-service-7d9c8b6f4-xyz12&#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;Last State:     Terminated&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Reason:       OOMKilled&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Exit Code:    &lt;span style=&#34;color:#ae81ff&#34;&gt;137&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Events:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Type     Reason     Age   From               Message&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Warning  Unhealthy  2m    kubelet            Readiness probe failed: HTTP probe failed with statuscode: &lt;span style=&#34;color:#ae81ff&#34;&gt;503&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Warning  BackOff    1m    kubelet            Back-off restarting failed container&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Reason: OOMKilled&lt;/code&gt; 和 &lt;code&gt;Exit Code: 137&lt;/code&gt; 明确说明容器是被 cgroup 杀了——进程实际用量超过了 &lt;code&gt;memory limit&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;第二步，看内存配置和真实用量：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ kubectl get deploy order-service -o jsonpath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{.spec.template.spec.containers[0].resources}&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;{&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;limits&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;requests&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cpu&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;512Mi&amp;#34;&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;$ kubectl top pod | grep order-service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;order-service-7d9c8b6f4-abc 980Mi&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;limit 设了 1Gi，但流量上涨后 RSS 已逼近 980Mi，剩余空间几乎为 0。一旦有请求峰值或 GC 不及时，立刻越线被杀。&lt;/p&gt;&#xA;&lt;p&gt;第三步，确认是不是内存泄漏。拉取一个还没被杀的 Pod 的堆信息：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ kubectl exec order-service-xxx -- jmap -histo:live &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; | head -15&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; num     &lt;span style=&#34;color:#75715e&#34;&gt;#instances         #bytes  class name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   1:        &lt;span style=&#34;color:#ae81ff&#34;&gt;420183&lt;/span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;71234560&lt;/span&gt;  java.util.concurrent.ConcurrentHashMap$Node&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   2:        &lt;span style=&#34;color:#ae81ff&#34;&gt;318902&lt;/span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;25512160&lt;/span&gt;  com.xxx.OrderCacheEntry&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   3:        &lt;span style=&#34;color:#ae81ff&#34;&gt;120033&lt;/span&gt;       &lt;span style=&#34;color:#ae81ff&#34;&gt;14403960&lt;/span&gt;  java.lang.String&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;OrderCacheEntry&lt;/code&gt; 实例高达 31 万个且持续增长——这是一个本地订单缓存，使用 &lt;code&gt;ConcurrentHashMap&lt;/code&gt; 但&lt;strong&gt;没有设置容量上限和过期策略&lt;/strong&gt;，活动期间订单不断写入，缓存无限膨胀，导致内存只涨不落。&lt;/p&gt;&#xA;&lt;p&gt;第四步，解释&amp;quot;雪崩&amp;quot;链条。Pod 被 OOMKilled 后重启，重启期间 &lt;code&gt;readinessProbe&lt;/code&gt; 在应用冷启动 + 缓存重建完成前一直返回 503，于是 Endpoint 不把流量切给它；而剩余存活副本要承接全部流量，内存进一步上涨，再次 OOMKilled——形成&lt;strong&gt;重启→探活失败→流量集中→再 OOM&lt;/strong&gt;的死亡螺旋。滚动更新因为新副本始终 &lt;code&gt;ready&lt;/code&gt; 不过半，卡死在 Progressing，无法自愈。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;应急（先止血）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;立即调大 &lt;code&gt;memory limit&lt;/code&gt; 到 2Gi、request 提到 1Gi，并临时把副本数扩到 12，分散单 Pod 压力，打破越线被杀的循环：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ kubectl scale deploy order-service --replicas&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;给 &lt;code&gt;readinessProbe&lt;/code&gt; 增加 &lt;code&gt;initialDelaySeconds: 30&lt;/code&gt; 与更宽容的 &lt;code&gt;failureThreshold&lt;/code&gt;，避免冷启动期被误判摘流（临时缓解，非根治）。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;紧急重启有泄漏风险的缓存：对 &lt;code&gt;OrderCacheEntry&lt;/code&gt; 增加容量上限（LRU，最大 5 万条）+ TTL（10 分钟），重新发版。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;给 Deployment 配置 &lt;code&gt;minReadySeconds&lt;/code&gt; 与 &lt;code&gt;progressDeadlineSeconds: 300&lt;/code&gt;，并在探针上加 &lt;code&gt;startupProbe&lt;/code&gt;，让冷启动阶段不被 readiness 误杀：&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;startupProbe&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;httpGet&lt;/span&gt;:&#xA;&lt;/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;/health&lt;/span&gt;&#xA;&lt;/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;8080&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;failureThreshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#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;periodSeconds&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;发版后副本稳定 &lt;code&gt;Running&lt;/code&gt;，上游超时率 5 分钟内回落到 0.3%，订单成功率恢复到 99.4%。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;无界本地缓存导致的内存泄漏&lt;/strong&gt;，在流量上涨时触顶 &lt;code&gt;memory limit&lt;/code&gt; 被 cgroup OOMKilled。雪崩的放大器是两点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;readiness 探针在冷启动期误摘流&lt;/strong&gt;：Pod 重启后缓存未预热完即被判定不健康，Endpoint 不接流量，存活副本承压更重。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;滚动更新卡死&lt;/strong&gt;：新副本始终达不到 ready 阈值，Deployment 既不能完成也不能自动回滚，故障窗口被人为拉长。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;节点有空余内存是假象——Kubernetes 的 OOM 是按 Pod cgroup 边界触发的，和节点总内存无关。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;所有本地缓存必须有界&lt;/strong&gt;：用 Caffeine/Guava Cache 显式设置 &lt;code&gt;maximumSize&lt;/code&gt; 与 &lt;code&gt;expireAfterWrite&lt;/code&gt;，禁止裸用 &lt;code&gt;ConcurrentHashMap&lt;/code&gt; 当缓存。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;内存 limit 留足 headroom&lt;/strong&gt;：limit 不应紧贴常驻用量，建议 limit ≥ 常驻峰值 × 1.5，并配置 &lt;code&gt;requests&lt;/code&gt; 与 &lt;code&gt;limits&lt;/code&gt; 一致以避免被调度到紧张节点。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;探针三件套合理配置&lt;/strong&gt;：&lt;code&gt;startupProbe&lt;/code&gt; 保护冷启动、&lt;code&gt;readinessProbe&lt;/code&gt; 控制接流、&lt;code&gt;livenessProbe&lt;/code&gt; 控制重启，三者职责分离，避免互相误伤。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;设置 PodDisruptionBudget + progressDeadlineSeconds&lt;/strong&gt;，配合告警，让滚动更新卡死能被及时发现并人工/自动干预。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;内存监控与压测&lt;/strong&gt;：对 &lt;code&gt;container_memory_working_set_bytes&lt;/code&gt; 设 80% 告警，大促前按 3 倍流量做容量压测，提前暴露泄漏。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障的教训是：&lt;strong&gt;Kubernetes 的 OOM 是 Pod 级的，不是节点级的&lt;/strong&gt;。看到节点有内存就以为安全，是典型的认知陷阱。更深的坑在于 OOMKilled 与探针、滚动更新的耦合——单点重启会被链路放大成整服务雪崩。排查时 &lt;code&gt;kubectl describe pod&lt;/code&gt; 里的 &lt;code&gt;Reason: OOMKilled&lt;/code&gt; + &lt;code&gt;Exit Code 137&lt;/code&gt; 是第一线索，再用 &lt;code&gt;jmap -histo:live&lt;/code&gt; 定位泄漏对象。容器环境下，任何&amp;quot;无限增长&amp;quot;的本地状态都是隐患，给缓存设边界、给探针分职责、给更新加兜底，三者缺一不可。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>公网 DNS 解析超时，CDN 回源为何大面积失败？</title>
            <link>https://blog.5772447.xyz/posts/38f14096/</link>
            <pubDate>Sun, 15 Jun 2025 17:25:39 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/38f14096/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们业务静态资源与部分动态接口走自建 CDN，边缘节点就近回源到源站集群 &lt;code&gt;origin.example.com&lt;/code&gt;。源站域名通过公网权威 DNS（第三方 DNS 服务商）解析，TTL 设为 60 秒。CDN 边缘节点默认开启&amp;quot;回源前解析域名&amp;quot;，每次回源连接都会经过本地 resolver 向公网权威服务器查询 &lt;code&gt;origin.example.com&lt;/code&gt; 的 A 记录。&lt;/p&gt;&#xA;&lt;p&gt;2025 年 6 月 15 日下午，我们收到了一波源站 502 的集中告警，时间点恰好在某第三方 DNS 服务商发布变更公告之后。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;17:00 起，多个省份的 CDN 边缘节点同时上报回源失败，错误码以 502 / 504 为主；&lt;/li&gt;&#xA;&lt;li&gt;监控显示源站本身 CPU、连接数、磁盘 IO 全部正常，源站健康检查通过；&lt;/li&gt;&#xA;&lt;li&gt;但从边缘节点 &lt;code&gt;curl&lt;/code&gt; 源站域名，偶发 &lt;code&gt;Could not resolve host&lt;/code&gt; 或卡住十几秒后才返回；&lt;/li&gt;&#xA;&lt;li&gt;直接 &lt;code&gt;curl&lt;/code&gt; 源站 IP（绕过域名）则秒回，说明源站服务无问题，问题在&amp;quot;域名解析 → 建连&amp;quot;这一段；&lt;/li&gt;&#xA;&lt;li&gt;告警呈现区域性、间歇性，并非全量节点同时挂。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#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;17:02:11 upstream connect error: origin.example.com resolve timeout (5s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;17:02:13 GET /api/v1/list -&amp;gt; 502 Bad Gateway (resolve failed)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;17:02:40 GET /api/v1/list -&amp;gt; 200 OK   (解析恢复)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步：确认问题在 DNS 侧还是源站侧。&lt;/strong&gt; 在边缘节点分别测 IP 直连与域名访问：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;time curl -s -o /dev/null -w &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%{http_code}\n&amp;#34;&lt;/span&gt; http://10.20.30.40/api/v1/list&#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;# 200，耗时 0.03s&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;time curl -s -o /dev/null -w &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%{http_code}\n&amp;#34;&lt;/span&gt; http://origin.example.com/api/v1/list&#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;# curl: (6) Could not resolve host，耗时 5.00s&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;直连秒回、域名超时，立即把火力集中到 DNS。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第二步：手动递归解析测试。&lt;/strong&gt; 用 &lt;code&gt;dig&lt;/code&gt; 指定公网 resolver 测试权威查询耗时：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;dig +trace +time&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; origin.example.com&#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;# 到权威服务器一步时长时间无响应，最后;; connection timed out; no servers could be reached&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;同时用本地 resolver 测：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;dig origin.example.com @223.5.5.5 +stats&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;;; Query time: &lt;span style=&#34;color:#ae81ff&#34;&gt;4823&lt;/span&gt; msec&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;;; SERVER: 223.5.5.5#53&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;223.5.5.5&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;权威服务器响应超过 4.8 秒，远超 CDN 回源解析超时阈值（默认 5s），部分请求直接超时。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步：对比多 resolver。&lt;/strong&gt; 换用多个公共 DNS 与运营商 DNS 逐一测：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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:#66d9ef&#34;&gt;for&lt;/span&gt; s in 223.5.5.5 119.29.29.29 8.8.8.8 1.1.1.1; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$s&lt;span style=&#34;color:#e6db74&#34;&gt;: &amp;#34;&lt;/span&gt;; dig origin.example.com @$s +short | head -1&#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;done&lt;/span&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;# 223.5.5.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:#75715e&#34;&gt;# 119.29.29.29: 10.20.30.40&lt;/span&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;# 8.8.8.8: (空)&lt;/span&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;# 1.1.1.1: 10.20.30.40&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;部分 resolver 解析为空，说明第三方权威 DNS 对部分递归节点的响应异常（后来确认是其一次变更导致 Anycast 节点路由抖动，部分 POP 点到权威服务器链路丢包）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第四步：关联时间线。&lt;/strong&gt; 查阅第三方 DNS 服务商状态页，发现 16:55 起其部分地区权威节点出现响应延迟升高公告，与我们 17:00 的告警完全吻合。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;紧急提高 CDN 回源解析超时阈值&lt;/strong&gt;，从 5s 提到 15s，减少瞬时超时导致的 502：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# CDN 边缘配置（示例，nginx 风格）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;resolver_timeout 15s;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;降低对公网 DNS 的实时依赖&lt;/strong&gt;：将 &lt;code&gt;origin.example.com&lt;/code&gt; 在 CDN 侧改为&amp;quot;IP 直连回源 + 长缓存&amp;quot;，即边缘节点不再每次解析域名，而是用配置里的固定源站 IP 列表回源，DNS 只作为兜底：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 回源配置改为 IP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;origin_upstream:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - 10.20.30.40:80&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - 10.20.30.41:80&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;为关键域名配置本地缓存 resolver&lt;/strong&gt;：在 CDN 节点旁部署 &lt;code&gt;dnsmasq&lt;/code&gt;，把 &lt;code&gt;origin.example.com&lt;/code&gt; 以较长 TTL 缓存，避免每次回源都打公网查询：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# dnsmasq.conf&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:#f92672&#34;&gt;=&lt;/span&gt;/example.com/119.29.29.29&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;local-ttl&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;300&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;等第三方 DNS 服务商 17:40 公告恢复后，逐步把解析超时限回 5s、回源恢复域名模式做灰度验证。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;CDN 回源链路对公网权威 DNS 的强实时依赖 + 过短的解析超时阈值&lt;/strong&gt;，在第三方 DNS 服务商出现区域 Anycast 抖动时被放大成大面积故障：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;CDN 边缘每次回源都做实时域名解析，TTL 仅 60 秒，意味着几乎没有本地缓存兜底；&lt;/li&gt;&#xA;&lt;li&gt;解析超时阈值设为 5s，一旦权威 DNS 响应超过 5s（实际到 4.8s 已濒临极限），请求直接判定失败返回 502；&lt;/li&gt;&#xA;&lt;li&gt;不同边缘节点就近的公网 resolver 不同，抖动只影响部分 POP，因此呈现&amp;quot;区域性、间歇性&amp;quot;特征；&lt;/li&gt;&#xA;&lt;li&gt;源站完全健康，却被 DNS 这一前置环节&amp;quot;误杀&amp;quot;。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;本质是架构上把&amp;quot;边缘回源&amp;quot;和&amp;quot;公网 DNS 稳定性&amp;quot;强耦合，缺少本地缓存与 IP 兜底两层缓冲。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;回源去域名化&lt;/strong&gt;：关键回源域名一律用 IP/SLB 地址直连，DNS 仅作为兜底，彻底解耦公网 DNS 抖动的影响。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;边缘节点本地解析缓存&lt;/strong&gt;：部署 dnsmasq/unbound，对源站域名做分钟级缓存，公网波动时仍能命中旧解析。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;多 resolver 冗余&lt;/strong&gt;：CDN 节点配置至少两个异构公共 DNS，单点 resolver 异常时自动切换。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;更合理的超时与重试&lt;/strong&gt;：回源解析超时阈值设为 10–15s，并加上解析失败后的指数退避重试，避免一次性超时即 502。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;权威 DNS 多服务商容灾&lt;/strong&gt;：核心域名开启 DNS 服务商主备（如主用第三方、备用云厂商 DNS），通过 NS 记录做冗余。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;外部依赖监控&lt;/strong&gt;：把&amp;quot;核心域名公网解析成功率/耗时&amp;quot;纳入主动拨测（如全国多节点 synthetics），第三方抖动可在用户感知前告警。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障教科书式地展示了&amp;quot;源站好好的，前端却 502&amp;quot;的典型链路：公网 DNS 这一看似与业务无关的底层服务抖动，通过 CDN 实时回源解析被放大成大面积故障。&lt;/p&gt;&#xA;&lt;p&gt;排查的抓手很简单——&lt;strong&gt;先做对照实验（IP 直连 vs 域名访问），把问题坐标从&amp;quot;源站/网络/应用&amp;quot;精确定位到&amp;quot;DNS 解析&amp;quot;&lt;/strong&gt;，后面的事就顺理成章了。架构层面的教训更值得记：任何一条关键链路都不该对外部单点（尤其公网 DNS）做零缓存的强实时依赖，本地缓存 + IP 兜底 + 多 resolver 冗余，才是抵御此类抖动的标配。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>域用户密码过期，定时同步任务为何批量失败？</title>
            <link>https://blog.5772447.xyz/posts/6f0650ff/</link>
            <pubDate>Thu, 01 May 2025 11:33:54 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/6f0650ff/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们部门维护着一套跨部门数据同步平台，负责把 ERP、CRM、WMS 三个业务系统的增量数据，在每天凌晨 01:00 统一抽取、清洗后写入数据仓库。平台跑在 6 台 Linux 应用服务器上，调度由一台独立的 cron 主机负责。出于统一身份管理的考虑，这 6 台机器和 cron 主机都加域（Active Directory），同步脚本通过域用户 &lt;code&gt;svc-sync&lt;/code&gt; 运行，该账号由安全团队统一纳管，强制 90 天改密。&lt;/p&gt;&#xA;&lt;p&gt;这个账号已经稳定运行了快一年。问题发生在 2025 年 5 月 1 日凌晨，恰逢五一假期，绝大多数同事在家，告警却准时在 01:05 炸了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;凌晨 01:05，企业微信告警群连续收到 6 条 &amp;ldquo;数据同步任务失败&amp;rdquo; 的告警，全部来自 6 台应用服务器。打开监控面板，发现以下现象：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;所有同步任务都在获取源数据连接阶段就失败，没有一条进入清洗环节；&lt;/li&gt;&#xA;&lt;li&gt;失败时间高度集中在 01:00–01:03，与 cron 触发时间吻合；&lt;/li&gt;&#xA;&lt;li&gt;白天手动用 &lt;code&gt;svc-sync&lt;/code&gt; 登录任一节点测试 SSH，提示密码错误；&lt;/li&gt;&#xA;&lt;li&gt;应用自身进程（如常驻的数据清洗守护进程）正常，只是&amp;quot;由 cron 拉起的脚本&amp;quot;失败。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;更奇怪的是，前一日（4 月 30 日）白天的手动同步回放测试一切正常，问题只出现在&amp;quot;定时自动跑&amp;quot;的场景，让人第一反应是 cron 配置被改了。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# 01:02 收到的部分告警原文&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[CRIT] job=sync_erp  exit=1  host=app-01  msg=source connect failed: Authentication failed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[CRIT] job=sync_crm  exit=1  host=app-02  msg=source connect failed: Authentication failed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[CRIT] job=sync_wms  exit=1  host=app-03  msg=source connect failed: Authentication failed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;第一步：确认 cron 是否执行。&lt;/strong&gt; 登录 cron 主机，查看 &lt;code&gt;/var/log/cron&lt;/code&gt;，任务确实在 01:00 被拉起，排除&amp;quot;任务没触发&amp;quot;的可能。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;grep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt; /var/log/cron | grep &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;May  1&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:#75715e&#34;&gt;# May  1 01:00:01 cron (svc-sync) CMD (/opt/sync/run_all.sh)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;第二步：缩小到认证环节。&lt;/strong&gt; 手动以 &lt;code&gt;svc-sync&lt;/code&gt; 身份执行脚本：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;sudo -u svc-sync /opt/sync/run_all.sh&#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;# ERROR 1045 (28000): Access denied for user &amp;#39;svc_sync&amp;#39;@&amp;#39;app-01&amp;#39; (using password: YES)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;但数据库里这个账号的密码没变过，说明不是数据库侧问题，而是本地用什么凭据去连。脚本通过 &lt;code&gt;kinit&lt;/code&gt; 拿 TGT 后再用 Kerberos 委托访问各系统。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第三步：检查域账号状态。&lt;/strong&gt; 在域控上用 &lt;code&gt;Get-ADUser&lt;/code&gt; 查看：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Get-ADUser svc-sync -Properties PasswordExpired,PasswordLastSet,AccountExpirationDate | fl&#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;# PasswordExpired     : 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:#75715e&#34;&gt;# PasswordLastSet     : 2025-02-01 01:18:33&lt;/span&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;# 计算 90 天后 = 2025-05-02，但策略在 5/1 凌晨缓存刷新即生效&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;账号 &lt;code&gt;PasswordExpired&lt;/code&gt; 已经是 &lt;code&gt;True&lt;/code&gt;。由于 4 月 30 日的手动测试用的是白天已缓存的 TGT，而 5 月 1 日 cron 拉起时票据缓存已过期、重新 &lt;code&gt;kinit&lt;/code&gt; 因密码过期直接失败，脚本拿不到新票据，于是连接各系统时报认证失败。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;第四步：定位为何白天没发现。&lt;/strong&gt; 该账号密码过期没有邮件提醒，且 &lt;code&gt;svc-sync&lt;/code&gt; 是服务账号，不在普通用户的&amp;quot;密码到期前 14 天提醒&amp;quot;流程里；值班同学假期前没做账号巡检。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;紧急恢复分为两步：&lt;/p&gt;&#xA;&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;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Set-ADAccountPassword svc-sync -Reset -NewPassword (ConvertTo-SecureString &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NewP@ssw0rd2025&amp;#34;&lt;/span&gt; -AsPlainText -Force)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Set-ADAccountControl svc-sync -PasswordNeverExpires $false&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Unlock-ADAccount svc-sync&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;统一更新所有节点的凭据缓存&lt;/strong&gt;。将新密码写入各节点的 keytab 与凭据文件，并重新生成 keytab：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;# 在域控用 ktpass 重新生成&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ktpass /out svc-sync.keytab /princ svc-sync@CORP.LOCAL /mapuser svc-sync /pass &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NewP@ssw0rd2025&amp;#34;&lt;/span&gt; /crypto ALL /ptype KRB5_NT_PRINCIPAL&#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;# 分发到 6 台节点后&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kinit -kt /etc/sync/svc-sync.keytab svc-sync@CORP.LOCAL&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;补跑 5 月 1 日数据&lt;/strong&gt;：由于没有进入清洗环节，直接重跑 &lt;code&gt;run_all.sh&lt;/code&gt;，全部成功，数据无遗漏。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;服务账号密码过期策略与定时任务的耦合缺乏监控&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;安全团队对 &lt;code&gt;svc-sync&lt;/code&gt; 启用了 90 天强制改密，但未把&amp;quot;服务账号密码到期&amp;quot;纳入运维告警；&lt;/li&gt;&#xA;&lt;li&gt;该账号不接收普通用户的到期提醒邮件，导致过期无人知晓；&lt;/li&gt;&#xA;&lt;li&gt;cron 场景每次执行都重新 &lt;code&gt;kinit&lt;/code&gt;，密码一旦过期即彻底失败；而白天手动测试依赖已缓存 TGT，掩盖了问题；&lt;/li&gt;&#xA;&lt;li&gt;凭据管理分散在 keytab 文件和脚本变量中，密码轮换需要人工逐节点更新，极易遗漏。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;本质上是把&amp;quot;人的账号生命周期管理&amp;quot;套用到了&amp;quot;机器服务账号&amp;quot;上，却没配套机器侧的无缝轮换机制。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;服务账号改用 gMSA 或密钥托管&lt;/strong&gt;：Windows 侧迁移到组托管服务账号（gMSA），由域控自动轮转密码，应用无需感知；Linux 侧接入 HashiCorp Vault 动态凭据，脚本启动时向 Vault 拉取短期密码。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;密码到期纳入监控&lt;/strong&gt;：在 Zabbix 里加一个脚本，对 &lt;code&gt;PasswordExpired -eq $true&lt;/code&gt; 或 &lt;code&gt;PasswordLastSet&lt;/code&gt; 距今天数 &amp;gt; 75 的账号发预警，提前 15 天提醒。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;凭据集中化&lt;/strong&gt;：所有 keytab 由配置管理（Ansible）统一推送，禁止手工散落，轮换时一条 playbook 全量更新。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务自恢复&lt;/strong&gt;：cron 脚本开头加 &lt;code&gt;kinit&lt;/code&gt; 健康检查，若失败先尝试用 Vault 刷新再执行，避免单点凭据失效直接拖垮整批任务。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;假期前巡检清单&lt;/strong&gt;：把服务账号有效期检查列入节假日前必做项。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障从表象看像&amp;quot;cron 挂了&amp;quot;，实则是&lt;strong&gt;域控侧账号密码过期&lt;/strong&gt;沿着 Kerberos 认证链路传导到了数据同步任务。一线排查的关键，是把&amp;quot;任务失败&amp;quot;往&amp;quot;认证失败&amp;quot;再往&amp;quot;账号生命周期&amp;quot;逐层下钻，而不是停留在调度层打转。&lt;/p&gt;&#xA;&lt;p&gt;最大的教训是：服务账号也是一种资源，它的生命周期（创建、轮换、过期、回收）必须纳入运维监控体系，不能因为&amp;quot;平时不出事&amp;quot;就放进盲区。把人工密码轮换替换为自动托管，才是杜绝此类问题复发的根本办法。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>秒杀接口大面积超时：Redis 缓存雪崩的定位与修复</title>
            <link>https://blog.5772447.xyz/posts/60f0dc58/</link>
            <pubDate>Tue, 11 Mar 2025 22:43:30 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/60f0dc58/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;我们的电商系统在大促期间会开放限量秒杀活动，秒杀商品几十款，单款库存几千到几万不等。秒杀接口 &lt;code&gt;POST /api/seckill&lt;/code&gt; 是系统流量入口，正常情况下 QPS 在 2000 左右，大促开场瞬间会冲到 30000+。&lt;/p&gt;&#xA;&lt;p&gt;为了扛住读压力，商品详情、库存余量、用户限购状态等热点数据全部缓存在 Redis 集群（3 主 3 从，每主 8G maxmemory）。缓存设计上，运营在后台批量导入秒杀商品时，统一把缓存 TTL 设置为 30 分钟，并且由于是同一时刻批量导入，大量 key 的过期时间高度集中在开场后的同一个时间窗口内。&lt;/p&gt;&#xA;&lt;p&gt;本次大促的秒杀在晚上 20:00 准时开始，商品导入动作发生在 19:25 左右，这意味着绝大部分缓存 key 会在 19:55 ~ 20:00 之间集中失效。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;20:00 活动一开抢，监控告警在 30 秒内全部触发：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;秒杀接口 P99 延迟从平时的 50ms 飙升至 8s，P999 直接超过 15s；&lt;/li&gt;&#xA;&lt;li&gt;网关层 504 超时大量出现，错误率从 0.1% 涨到 23%；&lt;/li&gt;&#xA;&lt;li&gt;Redis 集群 CPU 使用率被打满（各节点 user + sys 接近 100%），但 QPS 反而比平时低——因为大量请求已经穿透；&lt;/li&gt;&#xA;&lt;li&gt;后端 MySQL 主库连接数瞬间打满（max_connections=2000），出现 &lt;code&gt;Too many connections&lt;/code&gt;；&lt;/li&gt;&#xA;&lt;li&gt;订单创建成功率从 99.5% 掉到 41%，大量用户反馈&amp;quot;点了没反应&amp;quot;&amp;ldquo;一直在转圈&amp;rdquo;。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;最诡异的一点是：Redis 本身并没有宕机，节点都是 &lt;code&gt;connected&lt;/code&gt; 状态，但业务就是全面变慢。这让我们一开始怀疑是网关或应用层的问题，而不是缓存。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;第一步，先确认慢在哪里。在网关机器上抓取秒杀链路的 tracing：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;span: gateway -&amp;gt; seckill-svc -&amp;gt; redis (GET stock:sku_123)  3ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;span: gateway -&amp;gt; seckill-svc -&amp;gt; mysql (SELECT stock ...)    7200ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;span: gateway -&amp;gt; seckill-svc -&amp;gt; mysql (INSERT order)        timeout&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;火焰图清楚显示耗时全部卡在 MySQL 的 &lt;code&gt;SELECT stock&lt;/code&gt; 上，而本该走 Redis 的 &lt;code&gt;GET stock:sku_xxx&lt;/code&gt; 几乎不见了。第一反应是 Redis 挂了或者连接池耗尽。&lt;/p&gt;&#xA;&lt;p&gt;第二步，登录 Redis 节点验证。连接正常，但发现一个反常现象：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ redis-cli info stats | grep -E &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;instantaneous_ops_per_sec|evicted_keys|keyspace_hits|keyspace_misses&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;instantaneous_ops_per_sec:1850&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;evicted_keys:0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;keyspace_hits:201&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;keyspace_misses:1640&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;expired_keys:98231&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;keyspace_misses&lt;/code&gt; 远大于 &lt;code&gt;keyspace_hits&lt;/code&gt;，说明大量 key 查不到，请求全部穿透到 MySQL。再看 &lt;code&gt;expired_keys&lt;/code&gt;，在故障窗口内一秒过期近 10 万个 key——典型的&lt;strong&gt;集中过期&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;第三步，确认过期时间分布。抽样几个秒杀 key：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$ redis-cli TTL stock:sku_1001&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;integer&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; -2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ redis-cli TTL stock:sku_1002&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;integer&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; -2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ redis-cli --scan --pattern stock:* | head -5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stock:sku_1021&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ redis-cli TTL stock:sku_1021&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;integer&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;绝大多数热点 key 都已失效或即将在几秒内失效，印证了&amp;quot;批量导入时统一 TTL&amp;quot;导致的集中过期。这就是缓存雪崩：同一时刻大量 key 失效，所有请求同时回源数据库。&lt;/p&gt;&#xA;&lt;p&gt;第四步，确认数据库承压。&lt;code&gt;SHOW PROCESSLIST&lt;/code&gt; 里堆满了 &lt;code&gt;SELECT stock FROM seckill_stock WHERE sku=?&lt;/code&gt;，几乎都是 &lt;code&gt;Sending data&lt;/code&gt; 状态。MySQL 本身能力不足以承接 3 万 QPS 的纯读，连接池被瞬间占满，进而拖垮整个订单链路。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;应急止血（先恢复，再根治）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;临时对秒杀接口做&lt;strong&gt;请求合并 + 本地缓存降级&lt;/strong&gt;。在应用层对库存查询加一层 Caffeine 本地缓存（TTL 2s），即使 Redis 没值，也先返回上一次的非空结果，避免所有线程同时打库。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;给热点读加&lt;strong&gt;互斥锁（singleflight）&lt;/strong&gt;，同一 sku 的回源只允许一个线程查库并写回 Redis，其余线程等待结果：&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;9&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;// 伪代码：singleflight 回源&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;String val &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; redis.&lt;span style=&#34;color:#a6e22e&#34;&gt;get&lt;/span&gt;(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;if&lt;/span&gt; (val &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;    val &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; singleflight.&lt;span style=&#34;color:#a6e22e&#34;&gt;exec&lt;/span&gt;(key, () &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;        String dbVal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; db.&lt;span style=&#34;color:#a6e22e&#34;&gt;queryStock&lt;/span&gt;(sku);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        redis.&lt;span style=&#34;color:#a6e22e&#34;&gt;setex&lt;/span&gt;(key, baseTtl &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; random(0,300), dbVal); &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; dbVal;&#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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;紧急扩容 MySQL 只读从库，将库存读流量导向从库，主库只承接下单写。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;网关侧对 &lt;code&gt;/api/seckill&lt;/code&gt; 开启&lt;strong&gt;令牌桶限流&lt;/strong&gt;（20000 QPS），超出直接快速失败返回&amp;quot;活动太火爆&amp;quot;，保护后端不被彻底压垮。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;5 分钟后 P99 回落到 600ms，10 分钟后恢复到 120ms，订单成功率回到 92%。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是&lt;strong&gt;缓存 key 集中过期引发的缓存雪崩&lt;/strong&gt;，叠加了两个设计缺陷：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;TTL 高度一致&lt;/strong&gt;：运营批量导入时统一设 30 分钟 TTL，导致活动开场瞬间海量 key 同时失效，请求在极短时间内全部击穿到数据库。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;缺乏防穿透/防雪崩机制&lt;/strong&gt;：缓存未命中时没有任何合并、降级或随机抖动策略，数据库在没有任何缓冲的情况下直面 3 万 QPS 的回源洪峰。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Redis 没宕机但 CPU 打满，是因为雪崩期间大量 key 同时过期触发主动/被动淘汰扫描，加上连接风暴，使单节点处理效率骤降；而真正的瓶颈在下游 MySQL——它本就不是为承载全部读流量设计的。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;TTL 加随机抖动&lt;/strong&gt;：导入缓存时 TTL = 基础值 + 随机(0, 300s)，打散过期时间，避免集体失效。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;int&lt;/span&gt; ttl &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 1800 &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; ThreadLocalRandom.&lt;span style=&#34;color:#a6e22e&#34;&gt;current&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;nextInt&lt;/span&gt;(0, 300);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;redis.&lt;span style=&#34;color:#a6e22e&#34;&gt;setex&lt;/span&gt;(key, ttl, value);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;热点 key 永不过期 + 后台异步刷新&lt;/strong&gt;：对秒杀库存这类极热点数据，设为逻辑不过期，由定时任务在后台主动刷新，彻底规避过期瞬间空窗。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;回源合并&lt;/strong&gt;：全站接入 singleflight / 分布式锁，保证同一 key 同一时刻只有一个回源。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;多级缓存&lt;/strong&gt;：Redis + 应用本地缓存（Caffeine）双层，Redis 失效时本地缓存仍能兜底。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;数据库保护&lt;/strong&gt;：库存读走从库，写主库；并配置合理的连接池上限与熔断（Sentinel/Resilience4j），避免被回源打挂。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;压测与演练&lt;/strong&gt;：大促前对&amp;quot;缓存全失效&amp;quot;场景做专项混沌演练，验证降级链路可用。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障本质不是 Redis 性能问题，而是&lt;strong&gt;缓存生命周期设计缺陷&lt;/strong&gt;引发的雪崩。集中 TTL 是很容易被忽视的&amp;quot;定时炸弹&amp;quot;，平时相安无事，一到流量洪峰就炸。排查上，关键抓手是 Redis 的 &lt;code&gt;keyspace_misses / expired_keys&lt;/code&gt; 两个指标——它们能一眼定性&amp;quot;请求是否穿透&amp;quot;。记住：缓存层永远要假设自己会失效，回源必须有合并、必须有抖动、必须有降级。把数据库当成最后一道防线，而不是第一道承受洪峰的堤坝。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>核心交换机 STP 根桥被抢，广播风暴怎么来的？</title>
            <link>https://blog.5772447.xyz/posts/8256a5f2/</link>
            <pubDate>Mon, 03 Feb 2025 13:26:40 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/8256a5f2/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;公司园区网采用典型三层架构：核心层一台华为 S7706（以下简称 CORE）作为 STP 根桥，汇聚层两台 S5730，接入层大量 S5731 接入交换机，全网联一、二层均启用 MSTP（多生成树）。根桥 CORE 上通过 &lt;code&gt;stp root primary&lt;/code&gt; 设定为最优根，优先级 0（实际显示为 0/4096，按实例计），确保生成树拓扑稳定。&lt;/p&gt;&#xA;&lt;p&gt;节后复工第一天，行政楼 3 层新扩了 12 个工位，施工方临时搬来一台华为 S1730S 傻瓜型可网管交换机（以下简称 NEW）用于补点。该交换机按惯例应作为接入层叶子节点挂到现有接入交换机下，不配置 STP 优先级（用默认 32768），乖乖当阻塞端口的下游即可。中午 13 点左右，行政楼整层及相邻的 2、4 层陆续出现网络卡顿、视频会议花屏、部分工位甚至拿不到 IP。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;现场观察与监控告警汇总如下：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;行政楼 2/3/4 层用户大面积反馈“网页打开慢、钉钉转圈、共享文件夹访问超时”，但核心业务系统（位于数据中心）偶发可达，整体是“时通时断”的严重劣化，而非完全断网。&lt;/li&gt;&#xA;&lt;li&gt;登上汇聚交换机 &lt;code&gt;display interface brief&lt;/code&gt;，发现多个上联口入方向带宽长期 90%+，且 &lt;code&gt;Broadcast&lt;/code&gt; 计数每秒几万包疯涨：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Interface                  PHY   Protocol  InUti  OutUti  Broadcast(pps)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GE0/0/24                   up    up        98%    95%     42000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GE0/0/23                   up    up        97%    92%     39000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;接入交换机面板端口指示灯呈“集体疯狂闪烁”状态，典型广播风暴特征。&lt;/li&gt;&#xA;&lt;li&gt;网管平台 Zabbix 触发 &lt;code&gt;High Broadcast Ratio&lt;/code&gt; 与 &lt;code&gt;STP Topology Change&lt;/code&gt; 告警，且 &lt;code&gt;Topology Change Count&lt;/code&gt; 在几分钟内从 0 涨到 600+，说明生成树在频繁震荡重算。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;广播风暴 + 拓扑频繁变更，基本锁定在二层环路或 STP 异常，按“先抑制、再定位”的思路推进。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;先登录核心 CORE，查看当前根桥是否还是自己：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;display stp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-------[CIST Global Info][Mode MSTP]-------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Protocol Status       : Enabled&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Bridge Priority       : 0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Root Bridge ID        : 4c1f-ccxx-xxxx&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Root Cost             : 0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Root Bridge ID&lt;/code&gt; 的 MAC 不是 CORE 自己的桥 MAC，而是 &lt;code&gt;4c1f-cc...&lt;/code&gt;，说明根桥被别人抢走了！本应是自己（Cost 0、自己就是根），现在 Root Cost 仍是 0 只是因为命令行显示的是“到根的开销”，需要进一步比对。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;精确查看根桥身份：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;display stp root&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Root Bridge ID   : 4c1f-cc12-3456&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Root Bridge Cost : 0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;&lt;code&gt;4c1f-cc12-3456&lt;/code&gt; 经 MAC 前缀查询是华为 S1700 系列，正是那台新搬来的 NEW 交换机！它成了根桥。&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;查看 NEW 的 STP 优先级：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;display stp | include Bridge Priority&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;在 NEW 上回显 &lt;code&gt;Bridge Priority : 0&lt;/code&gt;（被施工方误设为 &lt;code&gt;stp priority 0&lt;/code&gt; 或 &lt;code&gt;stp root primary&lt;/code&gt; 想“保证稳定”），优先级高于 CORE，于是 STP 重新选举，NEW 抢占根桥。&lt;/p&gt;&#xA;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;根桥漂移后，原稳定拓扑被推翻， NEW 与周边交换机之间形成次优路径且出现临时环路窗口，广播帧在环路中无限泛洪，形成广播风暴。再查拓扑变更：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;display stp topology-change&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Topology Change Count : 612&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Last Topo Change Time : 2025-02-03 13:02:11&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;与告警时间吻合，确认 NEW 接入是触发点。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;目标是让 CORE 恢复根桥、消除环路、压制风暴。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;应急抑制：在汇聚/核心上临时对上联接入口开启广播抑制，先止血，避免风暴蔓延：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;interface GigabitEthernet0/0/24&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; storm-control broadcast min-rate &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt; max-rate &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;纠正根桥：将 NEW 的 STP 优先级改回默认，并取消其抢占设置：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;system-view&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stp priority &lt;span style=&#34;color:#ae81ff&#34;&gt;32768&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;undo stp root&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;强制 CORE 重新稳坐根桥（双保险）：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;system-view&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stp root primary&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;等待 STP 重新收敛后，再次 &lt;code&gt;display stp root&lt;/code&gt;，根桥 MAC 变回 CORE，&lt;code&gt;Topology Change Count&lt;/code&gt; 停止增长，端口 Broadcast pps 回落到个位数，用户网络在 3 分钟内恢复。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;事后复盘：NEW 作为临时补点本应只做接入，施工方却顺手配了根桥优先级。已要求所有接入层设备出厂/入场前统一刷标准配置模板，禁止任何非核心设备设置 &lt;code&gt;stp root&lt;/code&gt; 或优先级低于 8192。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因是 NEW 交换机被错误配置了 STP 优先级 0（等价于 &lt;code&gt;stp root primary&lt;/code&gt;），使其桥优先级高于原根桥 CORE。MSTP 选举根桥时比较“桥优先级 + MAC”，优先级数值越小越优，0 优于 CORE 的 4096（显示值），于是 NEW 被选举为新的根桥。&lt;/p&gt;&#xA;&lt;p&gt;根桥变更触发全网生成树重算：大量端口角色/状态翻转（根端口、指定端口、阻塞端口重新分配），在收敛的过渡窗口内，本应阻塞的冗余链路短暂进入转发态，与既有物理连线构成二层环路。广播帧、未知单播帧在环路中反复泛洪且无法 TTL 终结，迅速演变为广播风暴，表现为端口灯狂闪、Broadcast pps 爆表、终端卡顿断网。拓扑每次震荡又产生新的 TC（Topology Change）报文，进一步加剧不稳定，形成“变更—环路—风暴—再变更”的恶性循环，直到根桥归位、环路消除才停止。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;根桥保护（Root Protection）：在所有的接入交换机上联口配置 &lt;code&gt;stp root-protection&lt;/code&gt;，一旦收到更优 BPDU 直接将该口置为 &lt;code&gt;root-inconsistent&lt;/code&gt;（丢弃）状态，从协议层面杜绝下级设备抢占根桥。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;interface GigabitEthernet0/0/1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; stp root-protection&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;BPDU 保护（BPDU Protection）：在连接终端/临时设备的边缘端口开启 &lt;code&gt;stp edged-port enable&lt;/code&gt; 并全局 &lt;code&gt;stp bpdu-protection&lt;/code&gt;，收到 BPDU 立即 shutdown 边缘口，防止私接设备扰乱生成树。&lt;/li&gt;&#xA;&lt;li&gt;标准配置模板 + 入场审计：所有交换机（含临时补点）入场前必须刷公司标准模板，模板中明确禁止设置 &lt;code&gt;stp root&lt;/code&gt; 与低优先级，并由网络组验收后方可上线。&lt;/li&gt;&#xA;&lt;li&gt;环路防护与 TC 防护：开启 &lt;code&gt;loop-protection&lt;/code&gt; 与 &lt;code&gt;tc-protection&lt;/code&gt;，限制单位时间 TC 报文处理速率，避免频繁重算拖垮 CPU。&lt;/li&gt;&#xA;&lt;li&gt;监控加固：在 Zabbix 对 &lt;code&gt;Topology Change Count&lt;/code&gt;、&lt;code&gt;Broadcast pps&lt;/code&gt;、端口利用率设阈值告警，争取在风暴成形前发现。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这起广播风暴的根因不在“环路本身”，而在“根桥被抢”——一台被误配优先级的临时交换机颠覆了整网生成树，收敛窗口里出现的瞬时环路才是风暴的直接推手。排查关键在于第一时间 &lt;code&gt;display stp root&lt;/code&gt; 比对根桥 MAC，发现身份异常便知有人抢桥。最该记住的教训是：STP 不能只靠“约定”，必须用 &lt;code&gt;root-protection&lt;/code&gt;、&lt;code&gt;bpdu-protection&lt;/code&gt; 等协议机制把根桥和边缘口钉死，再配合标准模板与入场审计，才能避免“好心配置”变成全网故障。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>新购笔记本为何加不进 AD 域？出厂系统排障记</title>
            <link>https://blog.5772447.xyz/posts/8d80996a/</link>
            <pubDate>Mon, 13 Jan 2025 12:54:18 +0000</pubDate>
            <guid>https://blog.5772447.xyz/posts/8d80996a/</guid>
            <description>&lt;h2 id=&#34;一问题背景&#34;&gt;&lt;a href=&#34;#%e4%b8%80%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;一、问题背景&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;元旦后公司新采购了 30 台联想 ThinkPad T14 Gen4 笔记本，预装 Windows 11 专业版 23H2，用于研发部门新员工入职。资产入库后，桌面运维组按惯例在备货区统一加域（将计算机加入公司 AD 域 &lt;code&gt;corp.example.com&lt;/code&gt;），以便后续通过 GPO 下发安全基线、软件分发和漫游配置。&lt;/p&gt;&#xA;&lt;p&gt;公司 AD 环境概况：单林单域 &lt;code&gt;corp.example.com&lt;/code&gt;，两台域控制器 &lt;code&gt;DC01&lt;/code&gt;（10.10.0.11）、&lt;code&gt;DC02&lt;/code&gt;（10.10.0.12），均承担 DNS 角色；终端通过 DHCP 获取地址，正常情况下 DNS 应指向 &lt;code&gt;10.10.0.11&lt;/code&gt; 和 &lt;code&gt;10.10.0.12&lt;/code&gt;。加域操作在运维网段（VLAN 20，10.10.20.0/24）进行，与域控所在服务器网段（VLAN 10）三层互通。&lt;/p&gt;&#xA;&lt;p&gt;备货区交换机属于办公网，物理上能访问服务器网段。历史上一律是开箱即加域，从未出过问题。本次是年度最大批量采购，时间紧，所以直接流水线作业。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二故障现象&#34;&gt;&lt;a href=&#34;#%e4%ba%8c%e6%95%85%e9%9a%9c%e7%8e%b0%e8%b1%a1&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;二、故障现象&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;对第一台笔记本执行加域时，在“系统属性 - 计算机名”中点击“更改”，输入域名 &lt;code&gt;corp.example.com&lt;/code&gt; 并填写有权限加域的域账号后，弹出报错：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;查询域“corp.example.com”的域控制器时出错。&#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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;反复重试 3 次均相同。偶尔在输入域名瞬间出现另一种提示：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;但同一台笔记本可以正常上网、访问内网 OA 系统与共享文件夹（说明基础网络是通的），只是加域这一步始终失败。用同一镜像的其余 5 台样机测试，全部复现，说明不是单机个案，而是这批出厂系统的共性问题。&lt;/p&gt;&#xA;&lt;h2 id=&#34;三排查过程&#34;&gt;&lt;a href=&#34;#%e4%b8%89%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;三、排查过程&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;加域的本质是：客户端先通过 DNS 查询 &lt;code&gt;_ldap._tcp.dc._msdcs.corp.example.com&lt;/code&gt; 的 SRV 记录定位域控，再建立 LDAP/SMB 会话。报错“找不到域控制器”通常就是 DNS 解析或网络连通性问题，于是从 DNS 入手。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;查看本机 IP 配置：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;ipconfig /all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;关键输出：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   IPv4 地址 . . . . . . . . . . . . : 10.10.20.105(首选)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   子网掩码  . . . . . . . . . . . . : 255.255.255.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   默认网关  . . . . . . . . . . . . : 10.10.20.1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   DHCP 已启用 . . . . . . . . . . . : 是&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   DNS 服务器  . . . . . . . . . . . : 8.8.8.8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       202.96.128.86&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;发现问题：DNS 指向的是公网 DNS（Google 8.8.8.8 与当地运营商 DNS），而不是内网域控。这说明出厂系统里 DHCP 客户端虽然拿到了内网地址，但 DNS 被某种方式覆盖成了公网值。进一步确认是出厂镜像在“网络连接 - IPv4 属性”里手动勾选了“使用下面的 DNS 服务器地址”，把公网 DNS 写死。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;验证域控 SRV 记录是否可解析：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;nslookup -type&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SRV _ldap._tcp.dc._msdcs.corp.example.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;返回 &lt;code&gt;*** 找不到 _ldap._tcp.dc._msdcs.corp.example.com: 不存在的域&lt;/code&gt;，且服务器显示为 &lt;code&gt;8.8.8.8&lt;/code&gt; 的公网应答，证明公网 DNS 当然解析不出内网域控记录。&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;测域控连通性（先把 DNS 临时指向域控再测）：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;ping 10.10.0.11&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;来自 10.10.0.11 的回复: 字节=32 时间=1ms TTL=128&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;说明网络层到域控是通的，问题纯粹在 DNS 解析。&lt;/p&gt;&#xA;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;用 &lt;code&gt;nltest&lt;/code&gt; 进一步确认域定位能力：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;nltest /dsgetdc:corp.example.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;返回 &lt;code&gt;ERROR_NO_SUCH_DOMAIN&lt;/code&gt;，与 nslookup 结论一致。&lt;/p&gt;&#xA;&lt;h2 id=&#34;四解决方案&#34;&gt;&lt;a href=&#34;#%e5%9b%9b%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;四、解决方案&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根因明确：DNS 指向公网，无法解析域控 SRV 记录。临时与永久处理分两步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;临时加域（先让这台能进域）：手动把 DNS 改为域控，然后加域。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;netsh interface ip set dns name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;以太网&amp;#34;&lt;/span&gt; static 10.10.0.11&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;netsh interface ip add dns name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;以太网&amp;#34;&lt;/span&gt; 10.10.0.12 index&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;随后在“计算机名”中重新加域成功，重启后 &lt;code&gt;echo %logonserver%&lt;/code&gt; 显示 &lt;code&gt;\\DC01&lt;/code&gt;，确认已在域内。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;永久修复（针对整批机器）：由于出厂镜像里把 DNS 写死，单靠 DHCP 下发的 DNS 会被覆盖。两种做法：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;方案 A：在出厂首次开机前，用 PE 或脚本统一清除网卡写死的 DNS，改回“自动获取”，让 DHCP 下发的域控 DNS 生效。&lt;/li&gt;&#xA;&lt;li&gt;方案 B：直接调整备货区 DHCP 作用域，并在接入交换机上做 DHCP Snooping + Option 6 强制下发 &lt;code&gt;10.10.0.11,10.10.0.12&lt;/code&gt;，即便客户端写死也被覆盖（需网关支持）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;最终采用方案 A 批量脚本化处理，30 台在 1 小时内全部加域成功，并手动触发 &lt;code&gt;gpupdate /force&lt;/code&gt; 验证 GPO 正常应用。&lt;/p&gt;&#xA;&lt;h2 id=&#34;五根因分析&#34;&gt;&lt;a href=&#34;#%e4%ba%94%e6%a0%b9%e5%9b%a0%e5%88%86%e6%9e%90&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;五、根因分析&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;根本原因是 OEM 出厂镜像为了“开箱即能上网”的体验，在网卡 IPv4 属性中写死了公网 DNS（8.8.8.8）。当机器接入公司内网通过 DHCP 获取 IP 时，Windows 并不会用 DHCP 的 DNS 去覆盖“手动指定”的 DNS，于是 DNS 仍为公网值。&lt;/p&gt;&#xA;&lt;p&gt;加域依赖 DNS 定位域控：客户端查询 &lt;code&gt;_ldap._tcp.dc._msdcs.&amp;lt;域名&amp;gt;&lt;/code&gt; SRV 记录，公网 DNS 上不存在公司内网域的记录，所以返回“找不到域控制器 / 找不到网络路径”。注意这里不是域控不可达，而是定位阶段就失败了——因此即使能上公网、能开 OA，加域依然失败。&lt;/p&gt;&#xA;&lt;p&gt;此外，研发 VLAN 与服务器网段虽三层互通，但从严谨角度还应确认域控防火墙放行了加域所需的 RPC 动态端口与 TCP 88/389/445 等，本次这些均正常，排除在外。&lt;/p&gt;&#xA;&lt;h2 id=&#34;六预防措施&#34;&gt;&lt;a href=&#34;#%e5%85%ad%e9%a2%84%e9%98%b2%e6%8e%aa%e6%96%bd&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;六、预防措施&#xD;&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;标准化镜像：重新制作公司标准 WIM 镜像，出厂前清掉所有写死的公网 DNS，统一设为“自动获取”，并将该镜像写入采购验收 SOP，要求供应商出厂即灌装标准镜像。&lt;/li&gt;&#xA;&lt;li&gt;加域前检查脚本：在 MDT/Intune 或 PE 阶段自动执行 DNS 校验，发现 DNS 非内网地址直接阻断加域并告警。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div 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;&#xA;&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;&#xA;&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&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&#xA;&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;&#xA;&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;$dns &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;Get-DnsClientServerAddress -AddressFamily IPv4&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;.ServerAddresses&#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;$dns -notmatch &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^10\.10\.&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; Write-Warning &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DNS 异常: &lt;/span&gt;$dns&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;OU 预建计算机账号：采购计划中提前在 AD 对应 OU 预建计算机对象并重置密码，避免加域时权限/名称冲突引发的二次报错。&lt;/li&gt;&#xA;&lt;li&gt;验收清单化：把“DNS 指向域控、能 nslookup 出 SRV 记录”列为新机入库必检项，从源头消灭该类问题。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;七总结&#34;&gt;&lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;七、总结&#xD;&#xA;&lt;/h2&gt;&lt;p&gt;这次故障看似诡异——能上网、能开 OA 却加不了域，本质就是最基础的 DNS 问题。OEM 为出厂体验写死公网 DNS 的小动作，在内网加域场景下直接变成拦路虎。排查上只要牢牢记住“加域先查 DNS、先 &lt;code&gt;nslookup&lt;/code&gt; 域控 SRV 记录”这条铁律，5 分钟就能定位。真正的教训在流程：新机验收必须包含 DNS 与域解析校验，把标准镜像和预检脚本固化进采购 SOP，才能避免下一次批量踩坑。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
