中文
DNS 解析过程详解:从域名查询到 TTL 缓存的 Python 实验
浏览器输入一个域名之后,第一个可能阻塞请求的环节不是 HTTP,而是 DNS。DNS 的工程难点不在于记住“域名转 IP”,而在于理解递归解析、报文边界、TTL 缓存和失败时延之间如何相互作用。
本文从 RFC 1034/1035 的模型出发,用固定的四次查询实验,把缓存命中率如何改变用户感知延迟算出来。
一、从 stub resolver 到 authoritative server
应用通常把查询交给递归解析器。缓存缺失时,递归解析器可能依次询问 root、TLD 和 authoritative server;命中缓存时则直接返回仍在 TTL 有效期内的记录。响应报文的 header 至少携带 transaction ID、flags、question count 和 answer count。
二、手算 TTL 对平均延迟的影响
实验设缓存缺失为 42 ms,命中为 1 ms,查询发生在 t=[0, 10, 70, 80] 秒。第一次查询填充缓存并在 60 秒过期;70 秒时必须重新查询。
latencies = [42, 1, 42, 1] ms
average = (42 + 1 + 42 + 1) / 4 = 21.50 ms
hit_ratio = 2 / 4 = 50%
这不是说 TTL 越长越好:更长 TTL 降低解析成本,但也会延长地址迁移或故障切换的陈旧窗口。
三、运行环境与 Python 实验
运行环境:Python 3.10+ 与 Matplotlib;无需 root、网络连接或真实 DNS 服务器。实验读取仓库中的固定场景并重建 CSV 与图。
cd network-fundamentals-lab
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python src/dns_resolution_cache.py
expiry = -1
for at_second in [0, 10, 70, 80]:
hit = at_second < expiry
latency = 1 if hit else 42
if not hit:
expiry = at_second + 60
生成的 dns-cache-results.csv 明确记录了每次请求、HIT/MISS、延迟和过期时间。
四、报文层:为什么需要读 header
应用故障排查时,仅看 IP 不够。transaction ID 关联查询与响应,QR/RCODE 区分响应和错误,answer count 可以说明响应是否真正返回数据。实验包中的 C 程序解析固定响应 header:
cc -std=c11 -Wall -Wextra -O2 src/dns_packet_parser.c -o /tmp/dns_parser
/tmp/dns_parser
# txid=0x2a10 flags=0x8180 questions=1 answers=1
五、动画讲解:查询与缓存窗口
六、工程检查清单
- 记录查询域名、record type、resolver、TTL、RCODE 和完整耗时,而不是只记录最终 IP。
- 将权威 DNS 变更的 TTL 降低窗口与发布/回滚时间安排在一起。
- 排查延迟时区分应用 DNS 缓存、系统缓存和递归解析器缓存。
- 线上观察可使用
dig example.com A +noall +answer +stats,但其结果不可替代固定实验。
FAQ
TTL 为零能否消除陈旧响应?
它会显著减少缓存收益且仍无法消除所有中间行为;可控发布通常使用有计划的低 TTL 窗口。
为什么这篇文章不用抓包?
目标是让数值可重复。固定报文字节足以学习 header,而真实抓包会混入操作系统、网络与权限差异。
References
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1035: Domain Names - Implementation and Specification
下一篇从域名得到地址之后继续向下走,计算 CIDR 路由选择和 MTU 边界。
英文
DNS Resolution Explained: Build a TTL Cache and Packet Parser in Python
在独立页面打开When a browser receives a hostname, the first visible wait may happen before HTTP begins: DNS resolution. For engineers, DNS is not merely a name-to-address lookup. The useful questions are which resolver answered, whether a cached record was still valid, what the response header reported, and how those choices affected latency.
This article follows the RFC 1034/1035 model and uses four deterministic requests to calculate the latency value generated by the companion lab.
1. Resolution Paths And Cache State
A stub resolver normally asks a recursive resolver. On a cache miss, that resolver may traverse root, TLD, and authoritative knowledge before answering. On a cache hit, it may return a record while its TTL remains valid. A DNS response header still matters: transaction ID connects response to question, flags report state, and answer count says whether an answer is present.
2. A Hand Calculation For TTL Latency
Set a miss to 42 ms, a hit to 1 ms, and issue requests at seconds [0, 10, 70, 80]. The entry populated at second zero expires before second seventy.
latencies = [42, 1, 42, 1] ms
average = (42 + 1 + 42 + 1) / 4 = 21.50 ms
hit_ratio = 2 / 4 = 50%
A longer TTL is not automatically correct: it reduces resolution work but lengthens the stale-address period during migrations or failover.
3. Runnable Experiment
Environment: Python 3.10+ and Matplotlib. No root access, external network, or live DNS target is required; the run reads a bundled scenario file.
cd network-fundamentals-lab
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python src/dns_resolution_cache.py
expiry = -1
for at_second in [0, 10, 70, 80]:
hit = at_second < expiry
latency = 1 if hit else 42
if not hit:
expiry = at_second + 60
The generated dns-cache-results.csv records request time, cache state, latency, and expiry for auditing.
4. Reading A Header In C
For diagnosis, an IP address alone hides failures. The lab's C example decodes a fixed safe response header rather than sniffing real traffic:
cc -std=c11 -Wall -Wextra -O2 src/dns_packet_parser.c -o /tmp/dns_parser
/tmp/dns_parser
# txid=0x2a10 flags=0x8180 questions=1 answers=1
5. Animated Walkthrough
6. Engineering Checklist
- Log the queried name, record type, resolver, TTL, RCODE, and latency rather than only the final address.
- Coordinate lowered TTL windows with DNS migrations and rollback timing.
- Distinguish application, operating-system, and recursive-resolver cache behavior.
- Use
dig example.com A +noall +answer +statsfor observation only; its output is not the reproducible lab result.
FAQ
Does TTL zero eliminate stale responses?
It removes much of the cache benefit without controlling every intermediary. Planned, temporary low TTL is generally a more usable migration tool.
Why does this lab avoid packet capture?
Fixed bytes preserve repeatability and are sufficient for header reasoning, while captures add permission and environment variation.
References
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1035: Domain Names - Implementation and Specification
The next article takes the resolved address and calculates route selection and MTU boundaries.
浏览器输入一个域名之后,第一个可能阻塞请求的环节不是 HTTP,而是 DNS。DNS 的工程难点不在于记住“域名转 IP”,而在于理解递归解析、报文边界、TTL 缓存和失败时延之间如何相互作用。
本文从 RFC 1034/1035 的模型出发,用固定的四次查询实验,把缓存命中率如何改变用户感知延迟算出来。
一、从 stub resolver 到 authoritative server
应用通常把查询交给递归解析器。缓存缺失时,递归解析器可能依次询问 root、TLD 和 authoritative server;命中缓存时则直接返回仍在 TTL 有效期内的记录。响应报文的 header 至少携带 transaction ID、flags、question count 和 answer count。

二、手算 TTL 对平均延迟的影响
实验设缓存缺失为 42 ms,命中为 1 ms,查询发生在 t=[0, 10, 70, 80] 秒。第一次查询填充缓存并在 60 秒过期;70 秒时必须重新查询。
latencies = [42, 1, 42, 1] ms
average = (42 + 1 + 42 + 1) / 4 = 21.50 ms
hit_ratio = 2 / 4 = 50%
这不是说 TTL 越长越好:更长 TTL 降低解析成本,但也会延长地址迁移或故障切换的陈旧窗口。
三、运行环境与 Python 实验
运行环境:Python 3.10+ 与 Matplotlib;无需 root、网络连接或真实 DNS 服务器。实验读取仓库中的固定场景并重建 CSV 与图。
cd network-fundamentals-lab
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python src/dns_resolution_cache.py
expiry = -1
for at_second in [0, 10, 70, 80]:
hit = at_second < expiry
latency = 1 if hit else 42
if not hit:
expiry = at_second + 60
生成的 dns-cache-results.csv 明确记录了每次请求、HIT/MISS、延迟和过期时间。
四、报文层:为什么需要读 header
应用故障排查时,仅看 IP 不够。transaction ID 关联查询与响应,QR/RCODE 区分响应和错误,answer count 可以说明响应是否真正返回数据。实验包中的 C 程序解析固定响应 header:
cc -std=c11 -Wall -Wextra -O2 src/dns_packet_parser.c -o /tmp/dns_parser
/tmp/dns_parser
# txid=0x2a10 flags=0x8180 questions=1 answers=1
五、动画讲解:查询与缓存窗口
六、工程检查清单
- 记录查询域名、record type、resolver、TTL、RCODE 和完整耗时,而不是只记录最终 IP。
- 将权威 DNS 变更的 TTL 降低窗口与发布/回滚时间安排在一起。
- 排查延迟时区分应用 DNS 缓存、系统缓存和递归解析器缓存。
- 线上观察可使用
dig example.com A +noall +answer +stats,但其结果不可替代固定实验。
FAQ
TTL 为零能否消除陈旧响应?
它会显著减少缓存收益且仍无法消除所有中间行为;可控发布通常使用有计划的低 TTL 窗口。
为什么这篇文章不用抓包?
目标是让数值可重复。固定报文字节足以学习 header,而真实抓包会混入操作系统、网络与权限差异。
References
- RFC 1034: Domain Names – Concepts and Facilities
- RFC 1035: Domain Names – Implementation and Specification
下一篇从域名得到地址之后继续向下走,计算 CIDR 路由选择和 MTU 边界。
搜索问题
常见问题
这篇文章适合谁读?
这篇文章适合想用 进阶 难度理解“DNS 解析过程详解:从域名查询到 TTL 缓存的 Python 实验”的读者,预计阅读时间约 12 分钟,重点覆盖 DNS, Python, C, RFC 1035。
读完后下一步应该看什么?
推荐下一步阅读“CIDR、子网掩码与最长前缀匹配:用代码算清 IP 路由和 MTU”,这样可以把当前知识点接到更完整的学习路线里。
这篇文章有没有可运行代码或配套资源?
有。页面里的运行说明、资源卡片和下载入口会指向复现实验所需的命令、数据、代码或说明文件。
这篇文章和整个网站的学习路线有什么关系?
它会通过文章上下文、学习路线、资源库和项目时间线连接到同一主题下的其他内容。
文章上下文
网络基础原理
从 DNS、TCP、TLS 与 HTTP/3 到代理隧道、负载均衡和共享缓存,以可重现的代码和图分析网页请求路径。
配套资源
网络基础原理 / GUIDE
Network Fundamentals Lab 说明
安装、无权限安全边界、十个 Python 实验和三个 C 示例的运行说明。
网络基础原理 / DATASET
DNS TTL 结果 CSV
四次固定查询的 HIT/MISS、过期时间和解析延迟。
网络基础原理 / ARCHIVE
网络基础原理完整实验包
打包 Python/C 源码、固定场景、十份结果 CSV 与协议/代理图。
网络基础原理 / TOOL
网络请求链路交互演示
在浏览器里调整 TTL、前缀、丢包、握手 RTT 与缓存路径。
项目时间线
已发布文章
- DNS 解析过程详解:从域名查询到 TTL 缓存的 Python 实验 从 RFC DNS 报文与递归查询出发,用 Python 和 C 实验计算 TTL 缓存命中对解析延迟的影响。
- CIDR、子网掩码与最长前缀匹配:用代码算清 IP 路由和 MTU 手算 CIDR 网段、最长前缀匹配与 MTU/MSS 分段,并用 Python/C 输出固定路由结果。
- TCP 三次握手、重传与拥塞窗口:可运行的序列号实验 从 TCP sequence/ACK 和慢启动出发,用确定性丢包曲线与 localhost C socket 实验理解可靠传输。
- HTTPS 与 TLS 1.3 握手原理:密钥交换、证书和 RTT 实验 解释 TLS 1.3 消息 flight、证书与临时密钥交换,用安全的教学模型计算一次 RTT 握手。
- HTTP/2、HTTP/3 与 CDN 缓存:从网络瀑布图理解网页加载速度 用确定性 waterfall 模型拆解 HTTP/2、HTTP/3、QUIC stream 和 CDN HIT/MISS 对网页等待时间的影响。
- 正向代理与反向代理原理:连接路径、信任边界和时延计算 从连接方向和 TLS 终止点解释正向代理、反向代理与隧道代理,并用 Python 模型分段计算代理 hop 与缓存收益。
- HTTP CONNECT 与 HTTPS 代理隧道:TLS 边界和握手时延 以 RFC CONNECT 状态机解释 HTTPS 代理隧道、TLS 可见性和首次加密请求时延。
- SOCKS5 代理原理:协议字节、DNS 解析边界与泄漏风险 按 RFC 1928 拆解 SOCKS5 CONNECT 字节,通过安全编码实验比较本地 DNS 与代理侧域名解析。
- 反向代理负载均衡原理:队列、健康检查和可复现调度实验 用固定请求队列比较 round robin 与负载感知调度,并解释反向代理健康检查和重试边界。
- 代理缓存与重新验证:Cache-Control、ETag 和可观测性实验 依据 RFC 9111 计算共享缓存 MISS、HIT 与 304 revalidation 的时延,并解释缓存 key 和隐私边界。
已公开资源
- Network Fundamentals Lab 说明 安装、无权限安全边界、十个 Python 实验和三个 C 示例的运行说明。
- 网络基础原理完整实验包 打包 Python/C 源码、固定场景、十份结果 CSV 与协议/代理图。
- DNS TTL 结果 CSV 四次固定查询的 HIT/MISS、过期时间和解析延迟。
- CIDR 与 MTU 结果 CSV 最长前缀路由和 3600 B payload 分段计算结果。
- TCP cwnd 事件 CSV 逐轮记录 ACK、窗口和固定重传事件。
- TLS 1.3 flight 结果 CSV 固定 RTT 模型中的消息方向、时间点和教学共享值。
- HTTP/CDN waterfall 结果 CSV HTTP/2 与 HTTP/3 在冷暖缓存模型中的分阶段耗时。
- 代理路径时延结果 CSV 直接访问、正向代理隧道与反向代理缓存路径的分阶段等待。
- CONNECT/TLS 时间线 CSV 记录 CONNECT authority、隧道建立与加密 HTTPS 请求的状态边界。
- SOCKS5 DNS 边界 CSV 保存 ATYP、目标字节、请求长度和本机 DNS 解析计数。
- 代理负载均衡队列 CSV 比较 round robin 与 least queue 的 backend 选择和排队等待。
- 代理缓存重新验证 CSV 记录 MISS、HIT、304 重新验证、对象年龄和响应时延。
- 网络请求链路交互演示 在浏览器里调整 TTL、前缀、丢包、握手 RTT 与缓存路径。
- 网络基础原理专题分享图 用于分享 DNS、TLS、HTTP/3、代理隧道和缓存专题的 1200x630 SVG 图。
下一步计划
- 补充 IPv6 与 QUIC 报文观察笔记
- 继续用真实用户指标复查缓存与协议收益
