DNS解析与CDN加速原理深入解析
DNS 是把域名翻译成 IP 的分布式"电话簿",CDN 是把静态资源缓存到离用户最近节点的加速网络。 从输入 URL 到页面显示、CDN 回源与命中率,是前端性能与网络面试的高频题。
一句话概括
DNS(Domain Name System)干一件事:把人能记住的 www.example.com 翻译成机器要的 IP 93.184.216.34,是整个互联网的电话簿。没有它,换一次服务器 IP 全互联网都找不到你。
CDN(Content Delivery Network)则是把你的静态资源(js/css/图片/视频)缓存到全球边缘节点,让用户从最近的节点取,而不是跨半个地球打到你源站。延迟能从几百毫秒降到几十毫秒。
两者是前端性能优化的地基:DNS 决定”第一次握手前的耗时”,CDN 决定”资源下载的耗时”。面试常从”输入 URL 到页面显示”一路问到 CDN 回源、缓存命中率。下面把链路和坑讲清。
核心知识点
1. DNS 解析全流程(递归查询)
1
2
3
4
5
6
7
8
9
10
浏览器输入 www.example.com
├─ 1. 浏览器 DNS 缓存(命中即返回,Chrome 默认约 60s)
├─ 2. 操作系统缓存(hosts 文件优先级最高,其次系统缓存)
├─ 3. 本地 DNS(ISP / 8.8.8.8 / 223.5.5.5)查询
│ ├─ 有缓存 → 直接返回
│ └─ 无缓存 → 递归问:
│ 根服务器 "." → "去问 .com"
│ 顶级域 TLD ".com" → "去问 example.com 的权威服务器"
│ 权威服务器 → "答案是 93.184.216.34"
└─ 4. 结果逐层缓存(按 TTL)→ 浏览器拿到 IP → 开始 TCP 连接
耗时参考:浏览器/系统缓存命中≈1–10ms;完整递归≈30–200ms。所以”减少 DNS 查询次数”本身就是优化。
2. DNS 记录类型与 CDN 的钩子
| 类型 | 作用 | 示例 |
|---|---|---|
| A | 域名 → IPv4 | example.com → 93.184.216.34 |
| AAAA | 域名 → IPv6 | example.com → 2606:... |
| CNAME | 域名 → 另一个域名(别名) | cdn.example.com → xxx.cdn.cloudflare.net |
| MX | 邮件服务器 | @ → mail.example.com |
| TXT | 文本(SPF/DKIM 校验) | v=spf1 include:_spf.google.com ~all |
| NS | 指定域名服务器 | example.com → ns1.example.com |
CDN 的核心钩子就是 CNAME:你把 cdn.example.com CNAME 到 CDN 厂商的域名,CDN 的权威 DNS 再根据用户 IP(或 ECS 扩展)返回最近的边缘节点 IP——这就是”智能调度”。
3. DNS 缓存层级与 TTL
1
2
www.example.com. 3600 IN A 93.184.216.34
↑ TTL = 3600 秒,各级 DNS 按它缓存
1
2
3
浏览器缓存 ← 约 60s(Chrome 默认,不完全等于 TTL)
操作系统缓存 ← 按 TTL
本地 DNS ← 严格按 TTL(这里是全局缓存主力)
TTL 是双刃剑:
- 静态资源:用长 TTL(如 86400s),缓存命中率高
- 要切 CDN / 换 IP:先调短 TTL(如 300s),切换完成再调回长 TTL,避免旧 IP 缓存太久
4. CDN 工作原理与回源
1
2
3
4
5
6
用户请求 https://cdn.example.com/style.css
├─ DNS 解析 → 返回最近的边缘节点 IP
├─ 节点有缓存 → 直接返回(缓存命中 ✅)
└─ 节点无缓存 → 回源(去源站拉)→ 缓存到本地 → 返回(缓存未命中 ❌)
后续同区域用户访问同一资源 → 直接命中边缘缓存
回源(Origin Pull)触发场景:第一次冷启动、TTL 过期、源站手动刷新、动态内容不缓存。回源是要加延迟的,所以”命中率”是 CDN 第一指标(好 >90%,差 <70%)。
1
2
3
# 源站用这些头告诉 CDN 怎么缓存
Cache-Control: public, max-age=31536000 # 浏览器+CDN 都缓存 1 年
Cache-Control: s-maxage=86400 # 仅覆盖 CDN 侧缓存(1 天)
1
2
3
4
5
6
7
# 源站 Nginx:静态资源长缓存,HTML 不缓存(便于发版)
location ~* \.(js|css|png|webp|woff2)$ {
add_header Cache-Control "public, immutable, max-age=31536000";
}
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
}
5. 前端能做的 DNS 优化
1
2
3
4
5
6
<head>
<!-- dns-prefetch:提前只做 DNS 解析(最轻量) -->
<link rel="dns-prefetch" href="//api.example.com">
<!-- preconnect:DNS + TCP + TLS 全预建(确定要访问时用) -->
<link rel="preconnect" href="https://api.example.com" crossorigin>
</head>
1
2
3
dns-prefetch:只解析 DNS
preconnect :DNS + TCP + TLS
区别:确定会访问的域用 preconnect,可能访问的用 dns-prefetch,别无脑全 preconnect(占连接资源)
其实你每天都在用
- 输入网址后那几百毫秒:浏览器先走完上面整套 DNS 递归,拿到 IP 才连 TCP,慢的根因常在 DNS
ping/nslookup/dig:排查”域名解析不出来”的标配命令- 刷新页面 js/css 没更新:八成是 CDN 缓存没清,得在 CDN 后台 Purge 或给文件名加 hash 版本号
cdn.jsdelivr.net、cdnjs.cloudflare.com:你引的第三方库就是 CDN,自动就近<link rel="dns-prefetch">:大站在 head 里提前解析 API/CDN 域名,省掉首屏 DNS 等待- 切服务器 IP 后部分地区半天不生效:TTL 还没过期,老 IP 还在缓存,所以换 IP 前要先降 TTL
- 视频/大文件卡顿:可能命中了离你远的节点,CDN 调度没选对(或节点负载高)
常见误解(FAQ)
❌ 误区一:”DNS 解析就是查一次就完事,慢不到哪去”
整套递归要层层问根/TLD/权威服务器,完整未命中时 30–200ms 真不少;而且每引一个不同域(API、CDN、统计)就多一次。所以 dns-prefetch / preconnect 才有价值,把”隐形成本”提前吃掉。
❌ 误区二:”CDN 就是把文件复制一份到别的地方,永远比源站快”
错。CDN 有缓存未命中就要回源,此时反而比直连多一跳。命中率才是关键。另外源站响应慢、TTL 设太短、频繁发版,都会拉低命中率、放大回源。
❌ 误区三:”改了文件,CDN 马上就该显示新版”
不会。CDN 按 TTL 缓存,没到过期时间、也没手动 Purge,用户看到的还是旧文件。正确姿势:静态资源文件名带 hash(如 app.a1b2c3.js),内容变了文件名就变,CDN 当新资源缓存,旧的可安心长缓存。
❌ 误区四:”CDN 只加速图片/js,跟 API 没关系”
传统 CDN 确实主打静态。但现在有动态加速(DCDN):API 请求也走边缘节点,靠 BGP 优化路由、TCP/TLS 复用缩短到源站路径(不缓存内容,只优化网络)。实时性要求高的接口也能受益。
一句话总结
DNS 是把域名翻成 IP 的分布式电话簿,解析慢一拍首屏就慢一拍;CDN 用边缘缓存把资源送到用户家门口,命中率决定它值不值。前端要做的,是长缓存静态资源、用 dns-prefetch/preconnect 预解析、用文件 hash 解决更新失效——把这两层地基打稳,性能才有底气。