DNS 与 CDN
这一课你将能做到
- 说清 CDN 如何借 CNAME 接管域名、再用「权威智能解析 + 任播边缘 IP」把用户调度到最近节点
- 用
dig 和 curl 验证本站 CDN 是否生效,读懂 cf-cache-status、age、x-cache 等响应头
- 判断 CDN 调度异常(边缘选错、回源错误、缓存不命中)的层级并给出修复动作
为什么要学
本站用户分布在全国各地,甚至海外。如果所有访问都打到一台源站,新疆用户连华东机房,光网络往返就上百毫秒,高峰期还可能被带宽打爆。CDN 把内容缓存到离用户最近的边缘节点,而把用户「指」到哪个边缘节点,靠的正是 DNS——这是 DNS 除「翻译地址」之外最重要的进阶用途:流量调度。
理解 DNS 与 CDN 的协作后,你会明白:为什么同一个域名,北京和深圳 dig 出不同 IP;为什么 CNAME 目标是一串陌生的域名;为什么接入 CDN 后 TTL 通常很短。本课结合本站 Cloudflare 场景讲透调度链路。
先建立图像
用户(如成都)dig cdn.coderoadmap.cn
① 权威侧看到 CNAME
cdn.coderoadmap.cn CNAME cdn.coderoadmap.cn.cdn-vendor.net
│
② CDN 权威按「请求来源IP(EDNS Client Subnet)」智能回答
成都递归器来问 → 返回西南边缘节点 IP(任播)
上海递归器来问 → 返回华东边缘 IP
│
③ 用户连边缘节点
缓存有 ──► 直接返回(HIT,Age 递增)
缓存无 ──► 回源 origin.coderoadmap.cn 取内容 → 缓存 → 返回(MISS)
DNS 在 CDN 中的两个调度杠杆:
├─ 短 TTL(通常 60~300):节点故障/切换时快速重新调度
└─ EDNS Client Subnet(ECS,RFC 7871):递归器把用户网段带给权威,
让权威按用户真实位置(而非递归器位置)选边缘
| 名词 | 人话解释 |
|---|
| 边缘节点 | CDN 在各地机房的缓存服务器 |
| 任播 Anycast | 同一 IP 在多地宣告,路由自动选最近(Cloudflare 边缘 IP 即任播) |
| 回源 | 边缘没有缓存时去源站取 |
| HIT/MISS | 缓存命中 / 未命中 |
| ECS | EDNS 客户端子网,DNS 调度的定位依据 |
| 预热 | 上线前主动把内容推到边缘,避免首批用户 MISS |
跟着做
步骤 1:跟踪 CDN 的 CNAME 链与最终边缘 IP
dig cdn.coderoadmap.cn +short
dig +trace cdn.coderoadmap.cn | grep -E "CNAME|IN\s+A"
示例输出:
cdn.coderoadmap.cn.cdn-vendor.net.
104.21.5.10
172.67.133.10
本站用 Cloudflare(橙云),CNAME 链由 Cloudflare 内部完成,dig 直接看到任播边缘 IP。第三方 CDN 则通常在面板给一个 CNAME 目标,你添加记录后由其权威回答。
步骤 2:对比不同地区/递归器得到的边缘 IP
dig @1.1.1.1 cdn.coderoadmap.cn +short # 海外递归视角
dig @223.5.5.5 cdn.coderoadmap.cn +short # 国内递归视角
dig @119.29.29.29 cdn.coderoadmap.cn +short
任播 IP 可能相同(Cloudflare 所有节点共用同一批 IP,靠 BGP 选路),传统 CDN 则会看到按地区不同的 IP。「你查到的 IP」不代表「海外用户查到的 IP」,这也是排查跨地域问题时要多视角的原因。
步骤 3:验证缓存是否工作
# 连查两次同一静态资源:第一次 MISS、第二次 HIT
curl -I https://cdn.coderoadmap.cn/assets/logo.png
curl -I https://cdn.coderoadmap.cn/assets/logo.png
HTTP/2 200
server: cloudflare
cf-cache-status: HIT # DYNAMIC=不缓存;MISS=回源了;HIT=命中边缘
age: 126 # 已在边缘缓存的秒数
cache-control: public, max-age=86400
第三方 CDN 常见 x-cache: Hit from edge、x-cache-lookup、via: 等同类头。若一直 MISS,看步骤 6。
步骤 4:验证动态与静态的分流策略
# HTML 首页:通常不缓存或短缓存(DYNAMIC)
curl -I https://www.coderoadmap.cn/
# 带 hash 的静态资源:长缓存
curl -I https://cdn.coderoadmap.cn/assets/app-a3f9b2.js
# API:不缓存
curl -I https://www.coderoadmap.cn/api/tracks
典型策略:HTML no-cache(保证发版立即可见);带内容 hash 的 JS/CSS/图片 max-age=31536000, immutable(内容变则文件名变,可永久缓存);API 完全不走缓存。这些由源站 Cache-Control 头决定,CDN 遵循并可被页面规则覆盖。
步骤 5:检查回源链路
# 直连源站(灰云主机名),确认源站健康、回源 Host 能被识别
curl -I https://origin.coderoadmap.cn/
# 在 Cloudflare 规则中回源通常带 Host: 原始域名;
# 源站 Nginx 必须有匹配该 Host 的 server 块,否则回源拿到默认站内容
回源失败的常见表现:边缘返回 502/521(源站拒绝连接)、522(源站连接超时)、523/525(源站证书/SSL问题)。按第 6 课方式对齐回源协议(Full strict)。
步骤 6:排查「缓存不命中 / 命中率低」
# 1) 源站是否给了 no-cache/private/Set-Cookie(这些会让 CDN 不缓存)
curl -I https://源站或origin/资源 | grep -iE "cache-control|set-cookie|pragma"
# 2) 是否带了 vary:* 或每次 URL 带随机参数(?t=123)→ 被当成不同资源
# 3) 是否超过边缘允许的单个文件大小、或规则中该路径被设为 bypass
修复:源站为静态资源输出正确 Cache-Control: public, max-age=;去掉无关 Set-Cookie;发版预热关键 URL;统计命中率(厂商面板有 HIT 比例曲线)而非只看单请求。
步骤 7:演练一次「节点/回源切换」
# 模拟源站迁移:先把 TTL 确认在 300;修改回源地址(Cloudflare DNS 记录或回源规则)
# 观察边缘错误是否在 TTL 内收敛
for i in $(seq 1 6); do
curl -o /dev/null -s -w "%{http_code} %{time_total}\n" https://www.coderoadmap.cn/
sleep 60
done
短 TTL 的价值在此体现:调度关系变化最多一个 TTL 生效;若 TTL=86400,源站故障后切换要等一天。
讲清楚要点
- CDN 用 DNS 完成「就近调度」,用边缘缓存完成「内容加速」:DNS 是导航系统,边缘节点是仓库,两者缺一不可。
- CNAME 是 CDN 接管的标准入口:域名所有权不变,但解析路径被引到 CDN 权威,由其按网络位置动态作答。
- 智能解析依赖递归器位置或 ECS:没有 ECS 时权威只看到递归器 IP(用户与递归器通常同城,误差可接受);开启 ECS 精度更高但会把用户子网信息带给权威,存在轻微隐私权衡。
- 缓存策略由源站 Cache-Control 主导:CDN 不是「什么都自动缓存」,动态响应、Cookie、no-store 默认不缓存;规则可以覆盖但要克制。
- 任播让「同 IP 多地点」成立:用户不用 DNS 给出不同 IP,BGP 路由就近接入,故障时路由自动收敛。
- 回源是 CDN 与源站的契约:协议、Host 头、证书、SNI 都要对齐;回源放大(大量节点同时回源打爆源站)可用预热与合并回源规避。
- CDN 排障同样要分层:边缘命中问题看缓存头与规则;回源问题看源站;调度问题看 DNS 多视角与 ECS。
你可能会懵的地方
-
接入 CDN 后为什么源站日志看到的 IP 都是 CDN 的?
回源连接由边缘节点发起,和第 6 课橙云同理。源站要用 CF-Connecting-IP/X-Forwarded-For 取真实用户,并只把 CDN 回源网段加白名单,别开放全网。
-
CDN 边缘 IP 会不会坏?坏了用户怎么办?
会。任播 + 短 TTL 双保险:单节点故障时 BGP 先收敛(秒级),节点级问题靠 DNS 重新调度。这也是 CDN TTL 必须短的原因。
-
为什么启用 CDN 后某些地区反而更慢?
可能该地区缺少优质节点、跨境回源、或 ECS 缺失导致按递归器位置误调度。对比多地 dig + 边缘耗时,找 CDN 厂商调整调度或加区域节点。
-
HTTPS 证书在 CDN 场景是谁的?
边缘证书由 CDN 持有(用户↔边缘加密),源站证书另算(边缘↔源站)。可用 CDN 托管证书,也可上传自有证书;两阶段都加密才是完整 HTTPS。
-
刷新(Purge)和 TTL 是什么关系?
TTL 到期是自然失效;Purge 是主动通知边缘删除缓存(紧急下架/修错内容用)。频繁 Purge 会造成回源尖峰,正常发布应靠文件名 hash + Cache-Control 自然切换。
错法对照
| 错法 | 后果 | 正确做法 |
|---|
| HTML 也设永久缓存 | 发版后用户长期看旧页 | HTML no-cache;静态资源 hash 化后长缓存 |
| 资源 URL 带随机 query 还想命中 | 边缘按不同 key 全部 MISS | 固定 URL,版本号写进文件名 |
| 回源 Host 与源站 server_name 对不上 | 回源拿到默认页/404 | 回源 Host 保持原始域名 |
| CDN TTL 设 86400 | 故障调度一天不收敛 | 调度类记录 60~300 |
| 安全组只允许自己的办公 IP | CDN 回源被防火墙拦掉 | 按 CDN 官方回源网段放行 |
卡点急救
- 全站 522/连接源站超时:先确认源站服务与安全组(是否误封 CDN 回源段);直连 origin 验证;CDN 侧临时切备用源或灰度 bypass。
- 用户看到旧内容、强刷无效:边缘缓存未失效。Purge 对应 URL(必要时全量);检查源站 Cache-Control 是否过长;用 age/cf-cache-status 确认刷新已到边缘。
- 部分地区访问异常 IP:多递归器 dig 复现,检查 ECS 与调度策略;疑似单节点故障让厂商踢节点或临时改调度,短 TTL 保证快速收敛。
面试常问
-
请描述用户访问 CDN 资源时 DNS 做了什么。
用户查询命中 CNAME 指向 CDN 域名;CDN 权威根据递归器位置(或 ECS 携带的用户子网)做智能解析,返回就近的任播边缘 IP;短 TTL 保证调度可快速调整。用户连边缘:命中缓存直接返回,未命中则按回源 Host 与协议向源站取回再缓存。DNS 在此同时承担名字解析与全局流量调度两件事。
-
EDNS Client Subnet(ECS)解决什么问题?有什么代价?
公共递归器集中化后,CDN 权威只看到递归器 IP,可能把异地用户调度到递归器所在地节点。ECS(RFC 7871)让递归器把用户的部分子网地址转发给权威,调度按用户真实位置进行,命中率和延迟都改善。代价是用户子网信息暴露给权威链路、缓存 key 变多导致缓存碎片增大,因此只在需要的权威域上携带并做掩码截断。
-
CDN 命中率低怎么排查?
先看缓存状态头确认 MISS 的资源类型;再查源站响应:Cache-Control 是否 no-store/private、有无 Set-Cookie、vary 是否过宽、URL 是否带变化参数;然后核对缓存规则、文件大小限制与缓存分区;最后看是否预热不足导致回源放大。修复后以命中率曲线而非单次请求验收。
自测三问
- 画出从用户 dig 到边缘返回内容的完整链路,标注 CNAME、智能解析、回源各发生在哪。
- 为什么 CDN 的 DNS TTL 通常只有几分钟,而静态资源 Cache-Control 可以一年?两者各管什么?
- 边缘返回 522 与一直 MISS,分别属于哪一层?你先查什么?
小结一句话
CDN 借 CNAME 让 DNS 把用户调度到最近的任播边缘,再按源站 Cache-Control 决定缓存策略;短 TTL 保调度灵活,分层排障分清边缘、回源与权威。
延伸