一段话先讲明白
浏览器输入 google.com 到拿到 IP, 平均 15-150 毫秒。这段时间发生了 5 层缓存查询 + 最多 4 次跨网询问: 浏览器 cache → 系统 stub cache → 路由器 cache → ISP 递归 resolver cache → 询问根 (.) → 询问 TLD (.com) → 询问权威 (ns.google.com) → 拿到 A 记录。 每层 cache 命中越早越快 — 但缓存有 TTL 限制, 过期了得重新走一遍。下面一步一步拆。
一、完整 8 步流程图
┌─────────────────────────────────────────────────────────────┐
│ 浏览器 (Chrome / Firefox) 输入 google.com │
└────────────────┬────────────────────────────────────────────┘
│ ① 浏览器 DNS cache (Chrome ~60s)
↓ miss
┌─────────────────────────────────────────────────────────────┐
│ 操作系统 stub resolver + 系统 DNS 缓存 │
└────────────────┬────────────────────────────────────────────┘
│ ② 系统缓存 miss → 发 UDP 查询到路由器
↓
┌─────────────────────────────────────────────────────────────┐
│ 家用路由器 DNS 转发 + 路由器 cache │
└────────────────┬────────────────────────────────────────────┘
│ ③ 路由器 cache miss → 转发到 ISP 递归 resolver
↓
┌─────────────────────────────────────────────────────────────┐
│ ISP / 公共递归 (1.1.1.1 / 8.8.8.8 / 223.5.5.5) │
│ cache 命中: 直接返回, 整个过程 1-5ms │
│ cache miss: 进入下面"完整查询"流程 │
└────────────────┬────────────────────────────────────────────┘
│ ④ 问根 ns "google.com 在哪? "
↓
13 组根域名服务器 (a~m.root-servers.net)
│ ⑤ 回 "我不知道, 问 .com 的 NS: a.gtld-servers.net"
↓
.com TLD 权威服务器 (Verisign)
│ ⑥ 回 "我也不全, 问 google.com 的 NS: ns1.google.com"
↓
google.com 权威服务器 (Google 自己运营)
│ ⑦ 回 "google.com 的 A 记录 = 142.250.x.x"
↓
┌─────────────────────────────────────────────────────────────┐
│ ⑧ 递归 resolver 把答案缓存 (按 TTL), 返回给客户端 │
│ 沿途各层 cache 也存一份 │
└─────────────────────────────────────────────────────────────┘关键洞察: 真实场景里几乎从不走完整 8 步。大网站 IP 几乎永远在递归 resolver cache 里, 所以普通用户只走到第 ④ 步就返回。 只有冷门 / 长期未访问 / TTL 过期 / 新注册域名 才走完整流程。
二、5 层 DNS 缓存详解
DNS 这套系统在 1983 年设计时就考虑到了一个事实: 查询比改动多 10 万倍。 所以处处是缓存, 每层都按 TTL (Time To Live) 缓存一段时间。
| 层 | 位置 | 典型 TTL | 怎么查 / 清 |
|---|---|---|---|
| ① 浏览器 | Chrome / Firefox 进程内 | 60 秒 (Chrome) | chrome://net-internals/#dns 查 / 清 |
| ② 操作系统 stub | Windows DNS Client / macOS mDNSResponder / systemd-resolved | 跟 record TTL 一致 | Windows: ipconfig /displaydns 看, ipconfig /flushdns 清 |
| ③ 家用路由器 | 路由器内置 DNS forwarder | 看路由器实现 | 路由器重启清 / 后台手动清 |
| ④ ISP / 公共递归 | 1.1.1.1 / 8.8.8.8 / 223.5.5.5 | 跟 record TTL 一致 | 用户清不了, 等 TTL 过期 |
| ⑤ 权威服务器 | 域名所有者的 NS | 不缓存, 是数据源头 | — |
三、递归查询 vs 迭代查询 — 关键概念
3.1 递归 (Recursive)
客户端 (浏览器 / OS stub) 对 ISP 递归 resolver 说: "你帮我把 google.com 的 IP 找出来, 我不管中间过程"。 递归 resolver 必须完成整个查找, 把最终结果返回。
3.2 迭代 (Iterative)
递归 resolver 跟根 / TLD / 权威服务器对话时是迭代 — 我问根, 根说"问 .com", 我再去问 .com, .com 说"问 google", 我再去问 google。 每一步只跨一层, 不是"我问根, 根帮我搞定一切"。
客户端 ↔ 递归 resolver = 递归 | 递归 resolver ↔ 各级权威 = 迭代四、自己实测一下 — dig +trace
dig +trace 会强制做完整迭代查询, 显示每一步:
$ dig +trace cleanip.io
; <<>> DiG 9.10.6 <<>> +trace cleanip.io
;; global options: +cmd
; ① 第 1 跳 — 问根 (.)
. 518400 IN NS a.root-servers.net.
. 518400 IN NS b.root-servers.net.
... (13 个根 NS)
;; Received 525 bytes from 127.0.0.53#53 in 5 ms
; ② 第 2 跳 — 问 .io TLD
io. 172800 IN NS a0.nic.io.
io. 172800 IN NS b0.nic.io.
... (.io 的 6 个 NS)
;; Received 822 bytes from 198.41.0.4#53(a.root-servers.net) in 121 ms
; ③ 第 3 跳 — 问 cleanip.io 的权威
cleanip.io. 86400 IN NS nolan.ns.cloudflare.com.
cleanip.io. 86400 IN NS treasure.ns.cloudflare.com.
;; Received 109 bytes from 156.154.150.6#53(a0.nic.io) in 53 ms
; ④ 终于拿到答案
cleanip.io. 300 IN A 104.21.x.x
cleanip.io. 300 IN A 172.67.x.x
cleanip.io. 86400 IN NS nolan.ns.cloudflare.com.
cleanip.io. 86400 IN NS treasure.ns.cloudflare.com.
;; Received 154 bytes from 173.245.59.108#53(nolan.ns.cloudflare.com) in 12 ms解读:
- 整个流程 5 + 121 + 53 + 12 = 191 ms, 第一次冷查询确实慢
- 但下一秒同个域名再查只需要 1-2 ms, 因为 ISP 递归 cache 已经有了 (TTL 300 秒)
104.21.x.x / 172.67.x.x是 Cloudflare CDN, 我们站点真实源站 IP 被 CDN 隐藏
五、TTL 详解 — 缓存到底缓多久
TTL (Time To Live) 是权威服务器告诉所有递归 resolver "你最多缓存这么久"的字段, 单位秒。
| 典型 TTL | 含义 | 用在哪 |
|---|---|---|
| 60 (1 分钟) | 极短, 适合频繁切 IP 的服务 | 故障切换 / A/B 测试 |
| 300 (5 分钟) | 短, CDN 常用 | Cloudflare 默认 |
| 3600 (1 小时) | 中等 | 普通网站 |
| 86400 (1 天) | 长 | NS 记录 / 不常变的 A 记录 |
| 172800 (2 天) | TLD NS 标配 | .com / .io 等 NS 记录 |
| 518400 (6 天) | 根 NS 标配 | 13 根服务器的 NS 记录 |
注意: TTL 是"最大缓存时间", 各级 resolver 实际可以提前清缓存, 但不能延长。 所以即便你权威 TTL 是 1 小时, 实际有的 resolver 可能 10 分钟就重新查。
陷阱: 换 IP 前要先把 TTL 调短 (1-5 分钟), 等老 TTL 全过期后再切, 否则部分用户会持续 1+ 小时访问旧 IP。
六、DNS 记录类型速查
| 类型 | 含义 | 例子 |
|---|---|---|
| A | IPv4 地址 | cleanip.io → 104.21.x.x |
| AAAA | IPv6 地址 | cleanip.io → 2606:4700::6810:x |
| CNAME | 别名 (跳到另一个域名) | www.cleanip.io → cleanip.io |
| NS | 域名的权威 NS | cleanip.io → nolan.ns.cloudflare.com |
| MX | 邮件服务器 | cleanip.io → mx1.cleanip.io (10) |
| TXT | 任意文本 (SPF / DKIM / 验证) | SPF / Google verification |
| SOA | 区域起始, 包含主 NS / 邮箱 / 序列号 | 每个 zone 一条 |
| PTR | 反查: IP → 主机名 | 8.8.8.8 → dns.google |
| CAA | 谁能给我签 SSL 证书 | cleanip.io → letsencrypt.org |
| SRV | 服务记录 (含端口) | SIP / XMPP / Matrix |
七、DNS 优化 — 怎么让解析更快
7.1 选近的递归 resolver
中国大陆: 223.5.5.5 (阿里) / 119.29.29.29 (DNSPod) — 国内站点解析最快。 海外: 1.1.1.1 (Cloudflare 330 PoP, 全球最快) / 8.8.8.8 (Google 200 PoP)。 详见 公共 DNS 大全。
7.2 开 DoH (DNS-over-HTTPS)
走 HTTPS 加密 DNS 查询, 防 ISP 看 / 改 (防 NXDOMAIN 劫持)。Chrome / Firefox / Edge 都支持, 设置里开即可。
7.3 提前预热 (DNS Prefetch)
网站 <head> 里加 <link rel="dns-prefetch" href="//api.example.com">, 浏览器空闲时提前解析, 等真访问就是 cache hit。
7.4 用 CDN + Anycast NS
权威 NS 用 Anycast (Cloudflare / Route 53), 全球用户就近问到, 第 ③ 步耗时从 100ms 降到 10ms。
7.5 合理设 TTL
不会变的记录 (NS / MX) TTL 设长 (1-7 天); 可能切换的 A 记录设短 (5-60 分钟)。
八、常见问题
8.1 改了 DNS 但没生效 — 为啥
先想想: 当前 TTL 是多少? 改 DNS 后, 老 TTL 没过期之前, 所有递归 resolver 还会返回旧 IP。"全球生效" 一般要等 TTL × 2 时间 (考虑各 resolver 不同步)。
- 客户端:
ipconfig /flushdns(Windows) /sudo killall -HUP mDNSResponder(macOS) - 等公共递归 cache 过期: 1.1.1.1 / 8.8.8.8 可以用各自的 "purge" 工具手动清
8.2 部分用户能访问, 部分不能 — DNS 污染
中国大陆访问境外网站常见 — GFW DNS 注入 / ISP 劫持。换用 DoH (浏览器加密 DNS) 可绕过大部分 DNS 污染。
8.3 域名注册后多久能用
注册后, TLD 注册局把你的 NS 记录推送到 .com / .net 等顶级权威 — 一般 15 分钟到 24 小时。 .cn / .com.cn 可能需要 ICP 备案才能在中国大陆解析。
延伸阅读
- 为什么只有 13 组根域名服务器DNS 流程的最顶层 ④ 步
- 全球公共 DNS 大全选哪个 resolver 解析最快
- RFC 1035 — DNS 协议原文
- RFC 8484 — DoH (DNS-over-HTTPS)