CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
DNS 与域名解析/课时/解析过程
RawBlame
课时目录12 节

DNS 与域名解析

  1. 01DNS 是什么
  2. 02记录类型
  3. 03解析过程
  4. 04域名层次
  5. 05诊断工具
  6. 06本站域名配置
  7. 07DNS 与 HTTPS
  8. 08邮件相关记录
  9. 09K8s CoreDNS
  10. 10常见故障
  11. 11DNS 与 CDN
  12. 12综合练习

解析过程

递归解析、缓存、TTL。

30 分钟

解析过程

这一课你将能做到

  1. 用自己的话区分「递归查询」和「迭代查询」,并指出客户端、递归解析器、权威服务器三者各用哪种方式
  2. 用 dig +trace 完整跟踪一次 www.coderoadmap.cn 从根到权威的解析链路,逐跳解释
  3. 说清楚一次解析结果会经过哪几级缓存、分别受什么 TTL 控制,并动手清缓存验证

为什么要学

第 1 课我们建立了「DNS 是电话簿」的直觉,但真正回答「一次查询在网络上到底经历了什么」时,很多人只会背「先查根、再查顶级域、最后查权威」。背流程解决不了实际问题:为什么解析有时只要 2 毫秒、有时要 2 秒?为什么递归器问根时根不直接给答案?为什么 dig +trace 的输出和普通 dig 完全不是一回事?

理解递归与迭代的分工、缓存的层级和 TTL 的作用机制之后,你才能看懂第 10 课的故障现象——「解析超时」「首次访问慢、二次访问快」「改记录后全国生效时间不一样」全部源于这条链路。

先建立图像

① 客户端 ──递归查询──► 递归解析器(运营商/公共DNS,如 223.5.5.5)
   "我不管过程,给我最终答案"
                         │
②                       │  缓存有?─有─► 直接返回(最快,常见 1~20ms)
                         │  没有 ↓
                         ▼
③        迭代查询(每一级只回答"我知道谁可能知道")
   递归器 ──► 根服务器(.)
   根回答:".cn 的事去问 a.dns.cn(附胶水IP)"
   递归器 ──► .cn TLD 服务器
   TLD回答:"coderoadmap.cn 的权威是 ns1.cloudflare.com"
   递归器 ──► ns1.cloudflare.com(权威)
   权威回答:"www.coderoadmap.cn A 203.0.113.10,TTL 300"
                         │
④                       ▼
   递归器缓存答案(300秒)──► 返回客户端 ──► 客户端也缓存
角色它的职责查询方式
客户端(浏览器/系统)发起一次查询,等最终结果向递归器发递归查询
递归解析器替你跑完全程,缓存结果对各级权威发迭代查询
根 / TLD / 权威只回答自己负责的那一层被迭代询问

关键直觉:「递归」是对查询方的承诺(我帮你查到底),「迭代」是干活方式(我一层层自己去问)。一次完整解析里两者同时存在,只是发生在不同角色之间。

跟着做

步骤 1:普通查询,观察「递归器替你跑完」

dig www.coderoadmap.cn A

# Windows
nslookup www.coderoadmap.cn

看输出结尾的统计行:

;; Query time: 18 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)

SERVER 是你实际使用的递归解析器(这里是家用路由器,它再转发给运营商)。你只发了一个包、收了一个答案——中间的跑腿过程全被递归器藏起来了。

步骤 2:用 +trace 把迭代过程显形

dig +trace www.coderoadmap.cn A

输出分四段,每段对应一跳(示例经过精简):

; <<>> DiG 9.18 <<>> +trace www.coderoadmap.cn A
.                       518113  IN  NS   a.root-servers.net.     # 第1段:本机预取的根 hint
;; Received 525 bytes from 192.168.1.1#53(UDP) in 8 ms

cn.                     172800  IN  NS   a.dns.cn.               # 第2段:问根,根指到 .cn
;; Received 722 bytes from 198.41.0.4#53(a.root-servers.net) in 32 ms

coderoadmap.cn.         172800  IN  NS   ns1.cloudflare.com.     # 第3段:问.cn,指到权威
coderoadmap.cn.         172800  IN  NS   ns2.cloudflare.com.
;; Received 814 bytes from 203.119.25.1#53(a.dns.cn) in 24 ms

www.coderoadmap.cn.     300     IN  A    203.0.113.10            # 第4段:问权威,拿到答案
;; Received 64 bytes from 173.245.59.104#53(ns1.cloudflare.com) in 19 ms

注意:+trace 模式下是你的电脑直接做迭代,绕过递归器(除非加 +recurse 等参数),所以它展示的才是教科书全链路,也因此在部分 NAT/防火墙环境下可能拿不到结果。

步骤 3:手工迭代一遍(理解胶水记录)

# 先问根:不给递归(+norecurse),看根如何引荐
dig @a.root-servers.net www.coderoadmap.cn A +norecurse +nodnssec

# 再拿根返回的 .cn 地址继续问
dig @a.dns.cn www.coderoadmap.cn A +norecurse

# 最后问权威
dig @ns1.cloudflare.com www.coderoadmap.cn A +norecurse

第 1 跳的 ADDITIONAL 段里会附带 .cn 服务器的 IP,这就是胶水记录(Glue Record)——防止「要找 .cn 得先知道 .cn 的 NS 名字、解析那个名字又要问 .cn」的死循环。

步骤 4:观察缓存如何让查询变快

连续执行两次,对比 Query time 和 TTL:

dig @223.5.5.5 www.coderoadmap.cn A | grep -E "Query time|IN\s+A"
sleep 1
dig @223.5.5.5 www.coderoadmap.cn A | grep -E "Query time|IN\s+A"

典型现象:第一次几十毫秒(回源权威),第二次个位数毫秒;TTL 从 300 开始倒计时。等约 5 分钟后再查,TTL 会跳回 300、耗时也可能略增——说明递归器缓存过期、重新走了一遍迭代。

步骤 5:清本机缓存后复现

# Windows(管理员 PowerShell)
ipconfig /flushdns

# macOS(较新版本)
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

# Linux(systemd-resolved)
sudo resolvectl flush-caches

清完立刻查,TTL 显示的是递归器的剩余时间(本机缓存不影响它);但如果递归器缓存也过期了,你看到的 TTL 会「满血复活」。

步骤 6:量化一次「冷解析」的真实成本

# 第一次查询强制走新名字(可用刚建的测试记录),并打印耗时
dig @8.8.8.8 test-new.coderoadmap.cn A

# curl 视角看 DNS 占比
curl -o /dev/null -s -w "DNS解析: %{time_namelookup}s\n总耗时: %{time_total}s\n" https://www.coderoadmap.cn/

冷解析通常 20~150ms(视递归器与权威的网络距离);命中本机缓存时 time_namelookup 可低于 1ms。跨网(如国内递归器问海外权威)冷解析可能到 300ms 以上。

讲清楚要点

  1. 递归是一种「服务承诺」:客户端对递归器说「给我答案,别让我跑腿」;递归器负责跑完全程并承担缓存。家庭宽带默认用运营商递归器,企业可自建(dnsmasq、Unbound)。
  2. 迭代是实际跑腿方式:递归器问根,根不替它继续查,只给下一级的名字;逐级引荐直到权威。整条链路通常 3 跳:根 → TLD → 权威(有子域委派时更多)。
  3. 缓存分布在三级:应用/浏览器缓存(几分钟到几十分钟,各家策略不同)、操作系统缓存(受 TTL 约束)、递归解析器缓存(严格按 TTL,最多再叠加 SOA negative TTL)。
  4. 递归器可以主动缩短 TTL 上限:部分公共解析器对超长 TTL 会截断(如最大缓存 1 小时),但不会放大;客户端信任递归器返回的 TTL。
  5. 否定结果也缓存:NXDOMAIN 和 NODATA(名字存在但无该类型)的缓存时间取 SOA 的 minimum 字段(SOA 最后一列)与实际 SOA TTL 的较小值(RFC 2308)。
  6. UDP 为主、TCP 兜底:普通查询走 UDP 53;响应超过 512 字节(EDNS0 下通常 4096)、或区域传送(AXFR)时走 TCP。DNSSEC、大量 TXT 场景常见 TCP 回退。
  7. 根服务器不直接回答业务记录:全球只有 13 组根(a~m.root-servers.net,通过任播在全球有上千实例),它只负责引荐 TLD。

你可能会懵的地方

  • 递归和迭代到底差在哪?一句话说清? 递归查询要求「对方给最终答案」;迭代查询中对方只给「下一步该问谁」。客户端只做递归(一次),递归器对权威做迭代(一串)。

  • 根服务器只有 13 台,扛得住全球流量吗? 「13」是 13 个逻辑标识(a 到 m),每个标识通过任播(Anycast)在全球部署数百台物理实例,你实际访问的是网络最近的那一台。而且绝大多数查询被各级缓存挡掉,真正打到根的比例很低。

  • 为什么 dig +trace 在公司网络经常失败? 它需要本机直接对外发起 UDP 53 迭代查询,很多企业防火墙只允许流量经过指定递归器,直接外联 53 端口会被拦截。改用普通 dig 或在服务器/家用网络上做实验。

  • TTL=300 的记录,为什么 5 分钟后我浏览器里还是旧 IP? TTL 管的是 DNS 缓存,但浏览器还可能复用已建立的 TCP 连接、保持旧的 Happy Eyeballs 选择。关掉标签页重开、或重启浏览器才能彻底对齐。

  • CNAME 链上的 TTL 怎么算? 每一跳(CNAME 本身、最终 A)有各自的 TTL,整体缓存时间受限于最先过期的那一条。长 CNAME 链(3 跳以上)既慢又脆弱,应尽量避免。

错法对照

错法后果正确做法
认为客户端自己会一层层问根解释不了缓存与解析器行为客户端只问递归器;迭代是递归器的事
用 dig +short 判断「解析慢」+short 看不到耗时用完整 dig 看 Query time,或 curl 的 time_namelookup
只在本机清缓存就等公网生效递归器缓存仍在变更前降 TTL;用多公共解析器验证
排查时忽略 SERVER 字段不知道自己问的是哪台递归器先确认递归器,再对比公共解析器
把 CNAME 链设到 4 跳以上每跳一次 RTT,解析慢且易断链别名最多 1~2 跳,能直接 A 就不绕

卡点急救

  1. 首次访问慢、刷新后正常:典型冷解析开销。dig 看 Query time,若稳定很高,换个递归器(@223.5.5.5)对比;若只有特定递归器慢,问题在该递归器到权威的链路,可考虑换权威托管。
  2. 解析结果在权威改了,但递归器坚持旧值:确认权威侧 TTL;递归器按它取记录时拿到的 TTL 缓存,改 TTL 不会影响已经缓存出去的答案。等当前缓存过期,或联系递归服务商刷缓存(大型厂商多有刷新接口)。
  3. dig +trace 第一段就卡住:本机拿不到根 hint 或 UDP 外联被拦。加 @指定递归器 用普通查询代替,或在网络放行的机器上跟踪。

面试常问

  • 详细描述一次 DNS 递归解析的完整过程。 客户端先查浏览器与系统缓存;未命中则向递归解析器发起递归查询。递归器查自身缓存,未命中则开始迭代:问根服务器,根返回对应 TLD 的 NS 和胶水 IP;问 TLD,TLD 返回该域权威服务器的 NS;问权威拿到记录与 TTL。递归器把结果缓存后返回客户端,客户端也缓存。之后进入 TCP/TLS/HTTP。

  • 什么是胶水记录?为什么需要它? 胶水记录是父级区域(如 .cn)在委派 NS 时,在 ADDITIONAL 段额外附带的 NS 主机 IP。当某个域的权威服务器主机名就挂在该域自身下面(如 coderoadmap.cn 的 NS 是 ns1.coderoadmap.cn),会出现「解析 NS 名字又要问该域权威」的循环依赖;胶水让解析器不用先解析名字就能直接连到权威。

  • 递归解析器为什么要缓存?TTL 在其中起什么作用? 缓存把重复查询就地回答,既把解析延迟从几十上百毫秒降到亚毫秒,又极大降低了根/TLD/权威的负载。TTL 是权威为每条记录设定的最大缓存秒数,递归器过期后必须重新解析;它平衡了性能与数据新鲜度,也是运维控制变更传播速度的主要旋钮。

自测三问

  1. 客户端到递归器、递归器到权威,分别用的是递归还是迭代?为什么这样分工?
  2. 一条 TTL 300 的 A 记录刚被修改,最坏情况下哪些地方的用户还要等多久?为什么各地等待时间不同?
  3. dig +trace 与普通 dig 的输出差异,本质上反映了两者在链路中扮演什么不同角色?

小结一句话

客户端一次递归把活儿外包给解析器,解析器用三级迭代(根→TLD→权威)跑腿取答案,再靠各级缓存和 TTL 在速度与新鲜度之间做平衡。

延伸

  • RFC 1034 第 2、5 章:解析器与名字服务器模型
  • RFC 2308:查询的否定缓存
  • RFC 6891:EDNS0(扩展报文机制)
  • 根服务器官方介绍(Root Server Technical Operations)
  • 下一课预告:域名层次——根、顶级域、权威的层级结构,SOA 与委派到底怎么组织。
加载本节练习…
← 上一课记录类型下一课 →域名层次