DNS 解析时长毁了我精心设计的图床网络架构
本文最后更新于:2025年8月11日 凌晨
去年夏天,我兴致勃勃地写了好几篇博文,详细讲述了我如何搭建博客图床。核心目标很明确:分地区解析 DNS,让国内外的访客都能嗖嗖地加载图片,体验拉满。想法嘛,绝对是走在技术前沿的,堪称完美!然而……现实它总是喜欢给你来点小惊喜,对吧?
955 毫秒! 看到这个 DNS 解析时长的时候,我差点把刚喝下去的霸王茶姬喷在屏幕上。这简直就是一个隐形刺客,在我精心设计的图床网络架构背后,悄咪咪地给了致命一击。想象一下,访客满怀期待地点开你的博客,结果光是为了搞清楚图片服务器在哪,就要等上差不多一秒钟?这体验优化了个寂寞啊!
为啥之前没发现?这得“感谢”DNS 缓存这位老好人。它勤勤恳恳地帮后来的访客记住了答案,让我的本地测试和复访测试都一片祥和。直到最近,有群友向我反馈了首次访问时图片的加载速度过慢,我才如梦初醒。再结合最近为了秋招准备的八股文中里面关于 DNS 解析那套繁琐的流程(递归查询、权威查询、根域名、顶级域名……查个地址堪比查户口本),我瞬间锁定了罪魁祸首:首次访问时的 DNS 解析延迟。
来,复盘一下我那“曲折离奇”的 DNS 寻址之旅(访客视角):
- 访客想访问
static.031130.xyz
的图片。 - 查
031130.xyz
的权威 DNS: 问了一圈,发现权威服务器原来在 Cloudflare (国外)。 - Cloudflare 权威服务器回复: “哦,
static.031130.xyz
啊?它是个马甲 (CNAME
),真身是cdn-cname.zhul.in
,你去找它吧!” - 查
zhul.in
的权威 DNS: 这次权威服务器在 DNSPod (国内)。 - DNSPod 权威服务器回复 (针对国内用户): “
cdn-cname.zhul.in
也是个马甲 (CNAME
),它实际是small-storage-cdn.b0.aicdn.com
,接着找!” - 查
small-storage-cdn.b0.aicdn.com
: 最终,它可能还会再CNAME
到类似nm.aicdn.com
这样的 CDN 节点主机名。 - 最终获得 IP 地址,开始连接 CDN 节点下载图片。
发现问题没?关键的第一步和第二步,权威 DNS 查询指向了国外的 Cloudflare! 对于国内用户,虽然最终解析到的 CDN 节点 (small-storage-cdn.b0.aicdn.com/nm.aicdn.com
) 是国内的、速度飞快,但光是前两步跨越重洋的 DNS 查询,就足够让首次访问的用户体验跌入谷底。那个 955ms 的解析时长,基本就是花在跟国外 DNS 服务器“跨国聊天”上了。
优化方案:三管齐下,围剿 DNS 延迟
既然找到了病根,就得下猛药:
- DNS 预取 (
dns-prefetch
): 在博客的 HTML<head>
里,早早地加上<link rel="dns-prefetch" href="//static.031130.xyz">
。这相当于浏览器在渲染页面时,就悄悄开始解析图床域名了,等真需要加载图片时,DNS 结果可能已经准备好了,神不知鬼不觉。当然也可以使用 preconnect 等等更激进的策略,但本文着重讲 DNS 解析,因此不做拓展。 - 延长 DNS 记录的 TTL (生存时间): 把
static.031130.xyz
这个CNAME
记录的 TTL 值调大。以前都设置得较短,方便快速切换。现在为了缓存,适当延长(比如几小时甚至一天)。这样,一旦有用户解析过,本地 DNS 服务器就能记住更久,后续用户(包括同一用户再次访问)就能直接从缓存拿到结果,省掉跨国查询。 - 釜底抽薪:迁移权威 DNS! 这是最核心的一步。直接把
031130.xyz
域名的权威 DNS 服务器,从 Cloudflare 搬回国内 DNSPod。这样一来:- 访客的递归 DNS 服务器查询
031130.xyz
的权威服务器时,直接找到的就是国内的 DNSPod,响应飞快。 - DNSPod 直接告诉递归服务器
static.031130.xyz
->small-storage-cdn.b0.aicdn.com
完全在国内完成,丝般顺滑,不需要cdn-cname.zhul.in
当分区域解析的工具人 - 整个 DNS 解析链路都在国内高速完成,首次访问的 955ms 噩梦彻底拜拜。
- 访客的递归 DNS 服务器查询
效果如何?
受限于 DNS 缓存带来的测试困难,最终的效果确实很难在短时间内测试出来。但迁移权威 DNS 到 DNSPod + 调整 TTL + 加上预取之后,再测试首次访问的 DNS 解析时间总算是降到了可接受的程度,这才是 CDN 优化该有的样子!
教训总结:
- 别让 DNS 成为性能短板! 尤其是在涉及多地优化时,权威 DNS 的地理位置对首次访问延迟至关重要。能用国内的权威,就别用国外的。
- 缓存是好东西,但首次访问是软肋。 善用
dns-prefetch
和合理设置 TTL 能有效缓解。 - 监控和用户反馈是金。 自己的测试环境往往有缓存“美化”,真实世界的首次访问体验要靠更细致的监控和用户的火眼金睛(感谢反馈的朋友!)。
!!! 超级重要补充:警惕 CNAME 拉平 !!!
最后,必须给各位提个醒!如果你和我一样,需要依赖分地区解析来让访客访问到最近的 CDN 节点(比如让国内走国内CDN,国外走Cloudflare),那么千万要避开 CNAME Flattening
(CNAME 拉平) 这个“优化”方案!
- CNAME 拉平是什么? 简单说,就是权威 DNS 服务器(比如 Cloudflare)看到你设置了一个
CNAME
记录(比如static.example.com
->cdn.cname.target.com
),它主动帮你去找cdn.cname.target.com
的最终A
/AAAA
记录 (IP地址),然后把 最终的 IP 地址 直接返回给查询者,而不是返回CNAME
。 - 听起来很美好?它确实能减少 CNAME 链的长度! 但它有个致命缺点:权威 DNS 服务器在拉平解析时,会丢掉分地区解析的上下文!
- 为什么失效? 分地区解析 (
DNS View
或GeoDNS
) 的功能是在权威 DNS 服务器层面实现的。当权威服务器执行CNAME
拉平时,它是在它自己所在的位置去查询cdn.cname.target.com
的 IP。比如你的权威 DNS 在 Cloudflare (美国节点),它拉平查询时,拿到的cdn.cname.target.com
的 IP 大概率是给美国用户用的最优 IP。然后它把这个 IP 返回给了所有地区的查询者,包括中国用户!你精心配置的让中国用户解析到国内 CDN IP 的策略就完全失效了! - 结论: 如果你需要 分地区解析 (
GeoDNS
) 功能,绝对不要在你希望应用分地区解析的域名上启用CNAME Flattening
(或ALIAS
,ANAME
等实现类似拉平效果的功能)。老老实实用CNAME
指向另一个支持GeoDNS
的域名(就像我初始方案里static.031130.xyz
->cdn-cname.zhul.in
,而zhul.in
在 DNSPod 上做分地区解析),才能保证你的分流策略正确执行。