<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>504 on Zero Day Notes</title>
        <link>https://blog.5772447.xyz/tags/504/</link>
        <description>Recent content in 504 on Zero Day Notes</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Thu, 09 Jul 2026 16:58:00 +0000</lastBuildDate><atom:link href="https://blog.5772447.xyz/tags/504/index.xml" rel="self" type="application/rss+xml" /><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></channel>
</rss>
