常见故障
这一课你将能做到
- 按「客户端 → 递归器 → 权威」的分层模型,在 10 分钟内把 DNS 故障归入 NXDOMAIN、传播延迟、解析超时、5 秒延迟四类之一
- 对每类故障给出验证命令、根因判断与修复动作,而不是只会重启 Nginx
- 用
dig +trace、--resolve、时间戳对比构造完整证据链,写出可复盘的故障记录
为什么要学
线上故障处理和课堂练习最大的区别:你拿到的现象往往是残缺的。「网站打不开」可能是 DNS、可能是 443、可能是证书、可能是源站;「刚改了配置」不代表故障就出在配置。DNS 故障的特殊性还在于缓存——同一个时刻,不同用户、不同地区、不同递归器看到的答案可能完全不同,初学者很容易被「我这边是好的」带偏。
本课把前面所有知识收束成一套排障方法论:先分层、再归类、后修复。第 12 课综合练习会要求你独立跑完整套流程。
先建立图像
排障决策树:
域名打不开
│
├─ dig 返回 NXDOMAIN?
│ ├─ @多个公共解析器都 NXDOMAIN → 记录不存在/域名过期/Name拼错
│ └─ 只有本地递归器 NXDOMAIN → 否定缓存(SOA negative TTL)
│
├─ dig 新旧答案不一致(部分IP旧)?
│ └─ 传播延迟:看 TTL 倒计时;查权威多副本是否一致;等
│
├─ dig 超时(no servers reached / connection timed out)?
│ ├─ @公共DNS 也超时 → 本地网络/防火墙/UDP53 被拦
│ └─ 仅默认递归器超时 → 递归器故障,换解析器
│
└─ dig 正常但应用请求固定慢约 5 秒?
└─ UDP 丢包重传(含 K8s conntrack race)→ NodeLocal/cache/换TCP
| 故障类别 | 典型现象 | 根因层 | 核心证据 |
|---|
| NXDOMAIN | 名字不存在 | 权威数据/缓存 | status: NXDOMAIN |
| 传播延迟 | 部分地区旧值 | 各级缓存/多权威 | TTL、多解析器差异 |
| 解析超时 | 请求挂起 | 网络/递归器 | Query time 超时、换 @server |
| 5 秒延迟 | 成功但稳定慢 | UDP 丢包重传 | 耗时 ≈5s、抓包重传 |
总原则:DNS 层证实或排除之前,不动 Nginx;本地视图和公网视图对齐之前,不下结论。
跟着做
步骤 1:标准开场——三个固定命令
dig www.coderoadmap.cn A # 本地默认视图:看 status/TTL/SERVER
dig @8.8.8.8 www.coderoadmap.cn A # 公网视图1
dig @223.5.5.5 www.coderoadmap.cn A # 公网视图2(国内递归)
把三次结果并排记录:status、IP、TTL、Query time。三行数据立刻区分「全局故障 / 局部缓存 / 单递归器问题」。
步骤 2:处理 NXDOMAIN
# 1) 直问权威,绕过所有缓存
dig @ns1.cloudflare.com www.coderoadmap.cn A +norecurse
# 2) 看是否域名过期(whois;Windows 可在线查)
whois coderoadmap.cn 2>/dev/null | grep -iE "expir|status"
# 3) 若是「刚新增」的记录:查否定缓存时长
dig coderoadmap.cn SOA +short
判断路径:
权威也 NXDOMAIN → 记录真没有:面板是否保存?Name 是否拼错?是否建在别的 Zone?
权威有答案、递归 NXDOMAIN → 否定缓存:等 SOA minimum(如 3600s);急则换/刷递归器
whois 显示过期/暂停 → 续费并等待注册局恢复(与 DNS TTL 无关,可能数小时)
真实教训:某团队新建 api-v2 记录后全公司查不到,原因是测试时查过一次产生 NXDOMAIN,公司递归器按 SOA minimum 缓存了 1 小时——不是面板问题。
步骤 3:处理传播延迟
# 连续看 TTL 倒计时,确认只是缓存而非漏配
dig www.coderoadmap.cn A
# 多地域视角(可用在线 DNS 查询,或不同公共解析器)
dig @1.1.1.1 www.coderoadmap.cn +short
dig @9.9.9.9 www.coderoadmap.cn +short
正常情况:等当前 TTL(记录保存时下发的旧 TTL,改 TTL 不影响已缓存答案)
权威多副本不一致:直问每台权威 +norecurse;托管商侧同步问题提工单
急需快速生效:变更前 24h 先把 TTL 降到 300;已改完的只能等,别反复改记录
注意区分 NXDOMAIN 与「旧 IP」:旧 IP 但 status=NOERROR 是传播;名字直接没有是另一类。
步骤 4:处理解析超时
# 1) 换解析器立刻区分「递归器挂了」还是「本机网络挂了」
dig @8.8.8.8 www.coderoadmap.cn A
dig @223.5.5.5 www.coderoadmap.cn A
# 2) 测 53 端口可达性(TCP 测,排除 UDP 被单独丢弃)
# Linux/macOS
nc -vz -w3 8.8.8.8 53
# Windows PowerShell
Test-NetConnection 8.8.8.8 -Port 53
# 3) 强制 TCP 查询,判断是否 UDP 路径问题
dig +tcp www.coderoadmap.cn A
所有外部递归器都超时:本机出口/UDP53 被拦(公司安全策略、VPN、路由器故障)
仅默认递归器超时:该递归器故障 → 临时换公共 DNS,通知运营商/网管
TCP 正常 UDP 失败:UDP 被 QoS/防火墙丢弃,用 +tcp 临时绕过并找网络侧
步骤 5:处理 5 秒延迟
# 1) 重复查询观察耗时分布:命中缓存很快,丢包时稳定 ~5s
for i in 1 2 3 4 5; do dig www.coderoadmap.cn | grep "Query time"; done
# 2) 抓包看重传(Linux;macOS 同理)
sudo tcpdump -ni any port 53
# 3) 应用侧验证:首次调用慢、紧接着正常
curl -o /dev/null -s -w "%{time_namelookup} / %{time_total}\n" https://www.coderoadmap.cn/
tcpdump 典型证据:同一查询(同 id)发出后约 5 秒重发,随后收到应答——首包在链路中被丢弃。修复:
公网终端:换递归器(路径不同,丢包消失);检查本地路由器/光老化 MTU 与 NAT
Linux 服务器:查 conntrack 表是否满(dmesg | grep -i conntrack),调大 nf_conntrack_max
K8s:NodeLocal DNSCache + 扩 CoreDNS(见上一课)
应用:JVM/连接池加 DNS 缓存、改用长连接,避免每次调用都解析
步骤 6:DNS 正常但站点仍坏——完成分层交接
# 绕过 DNS 直连 IP,验证源站自身
curl -I --resolve www.coderoadmap.cn:443:203.0.113.10 https://www.coderoadmap.cn/
# 若走 CDN:对比边缘与源站
curl -I https://www.coderoadmap.cn/ # 走 CDN
curl -I https://origin.coderoadmap.cn/ # 直源站
直连源站 200、走域名失败 → 交给 CDN/网络层继续查;直连也失败 → DNS 已洗清,排查 Nginx/证书/应用。排障结束的标志不是「好了」,而是证据链完整指向某一层。
步骤 7:写故障记录(时间线格式)
10:00 收到工单,现象/影响范围
10:02 三条 dig 对比:归类为传播延迟
10:05 dig +norecurse 确认权威已为新IP,TTL 300
10:08 结论:旧答案缓存,预计 10:10 前全网生效
10:12 多解析器复查一致,关闭
改进项:变更 TTL 已提前降至 300,本次无需改进
讲清楚要点
- 先分层再动手:客户端(hosts、本机缓存)→ 递归器(缓存、可达性)→ 权威(数据、多副本),逐层排除。
- NXDOMAIN 也有 TTL:否定缓存让「查不到」同样会被粘住,这是新增记录「查不到」的隐性原因。
- 传播延迟不是故障:它是 TTL 机制的正常表现;真正的故障是「超过 TTL 仍旧」或「权威本身不一致」。
- UDP 无连接、无重传,重传由解析器库做:因此 DNS 层丢包表现为固定秒级(glibc 5s、musl 较短)停顿,而非报错。
- 换递归器是最便宜的止血动作:既能立刻恢复,又能作为诊断手段区分故障层。
- 证据要包含时间和具体服务器:没有时间戳,缓存类问题无法复盘;只说「dig 了」没有 @谁,结论不可复核。
- 多 A 记录无健康检查:一条坏 IP 会让一部分用户稳定失败(拿到坏 IP 先超时再换),排障时 dig 看到多条记录要逐个测。
你可能会懵的地方
-
ping 域名正常解析、浏览器还是打不开,怎么继续?
DNS 已排除。按 curl -I https://域名 看 HTTP/TLS:连接拒绝查 443 与安全组;证书告警查 SAN;超时查防火墙 MTU;502/504 查 Nginx 上游。
-
改 TTL 能加速已经缓存的旧答案失效吗?
不能。缓存时长在答案下发时就确定了。改 TTL 只影响下一次回源后新答案的缓存时间。这也是变更前提前降 TTL 的原因。
-
为什么手机流量和公司 Wi-Fi 结果不同?
两边递归器不同:运营商移动网用自己的递归,公司用企业转发。缓存状态与策略各自独立,多解析器对比正是为此。
-
dig 一次成功一次超时,抖动型怎么查?
先怀疑 UDP 丢包(跑步骤 5)与递归器负载;连续 20 次统计成功率,换递归器对照。抓包看是查询没出去还是应答没回来。
-
CDN 场景下 dig 出来的 IP 全是 CDN 的,怎么验证源站记录?
用独立的灰云/回源主机名(如 origin.域)查;它不被代理、返回真实源 IP。不要试图从代理记录里「挖出」源 IP。
错法对照
| 错法 | 后果 | 正确做法 |
|---|
| 不 dig 直接重启 Nginx/服务器 | 掩盖时间线,且大概率无效 | 三条 dig 开场 |
| 只在自己电脑验证就宣布恢复 | 递归器/地区差异未覆盖 | 多公共解析器 + 等 TTL |
| 传播期反复删改记录 | 每次改动重置缓存观察,越改越乱 | 改一次,看 TTL,耐心等 |
| 把 5 秒卡顿归因于数据库慢 | 查错方向,错过 DNS 修复窗口 | 先看 time_namelookup 与抓包 |
用 ping IP 判断权威服务器是否健康 | ping 通不代表 53 端口在服务 | 直接 dig @该IP 看应答 |
卡点急救
- 全公司打不开、外部正常:公司递归器或出口故障。临时下发公共 DNS(223.5.5.5/119.29.29.29)恢复业务,同步查企业 DNS 设备。
- 权威面板改了记录但公网全部仍旧且远超 TTL:检查注册商 NS 是否仍指旧权威(两套系统在跑);确认无 DNSSEC 链失效(RFC 4035,签名坏了递归器会返回 SERVFAIL 而非旧值,注意区分)。
- 多 A 记录中一台宕机,部分用户失败:立刻删除坏 A(TTL 短时快速止血),再修机器;长期应改用带健康检查的 LB,别让用户端去试错。
面试常问
-
用户反馈网站打不开,你的排查思路是什么?
先分层:本机 dig 看 status/TTL/SERVER,再用多个公共解析器对齐公网视图。NXDOMAIN 查权威数据、域名有效期和否定缓存;新旧不一致判定传播,看 TTL 与多权威一致性;超时换解析器、测 53 端口、区分 UDP/TCP;固定 5 秒卡顿抓包看 UDP 重传(含 conntrack)。DNS 排除后用 curl --resolve 直连源站验证站点。全程记录时间线。
-
什么是 DNS 传播延迟?为什么无法做到全球瞬时生效?
权威记录修改后,答案已按旧 TTL 缓存在用户系统和全球递归器中,未过期前不会重新查询,因此各地旧答案存活时间取决于各自缓存还剩多少——从 0 到一个 TTL 不等,且各地不同。想缩短传播窗口只能提前降低 TTL;修改本身不能撤销已经发出的缓存。
-
DNS 解析时好时坏、应用出现几秒卡顿,可能什么原因?
UDP 53 查询或应答在链路中丢失,解析器等待重传计时器(常见 5 秒)后重发成功:表现为抖动型固定秒级延迟。常见诱因有递归器过载、NAT/conntrack 表满(尤其 K8s SNAT 竞态)、UDP 被 QoS。验证靠重复 dig 统计与 tcpdump 看重传;解决靠换递归器、NodeLocal DNSCache、调 conntrack 或改用 TCP/长连接。
自测三问
- 四条故障线的判定证据分别是什么?你用哪三条命令做开场?
- 新上线子域后「公司查不到、外网正常」,给出两种可能根因与对应命令。
- 为什么改 TTL 救不了已经缓存的旧答案?正确的变更节奏是什么?
小结一句话
DNS 排障 = 先按客户端/递归器/权威分层,再归入 NXDOMAIN、传播、超时、5 秒四类,用带时间戳的多解析器证据链定位,证据未齐不动应用。
延伸