第 11 章 网络层(下):DNS 与 CDN 初识
副题:问路与抄近道——域名怎么变成 IP,以及"让旅程变短"的 CDN 为什么存在
第 10 章我们跟着请求走完了网络段的"上路"部分:报文写好了、连接建好了、加密加上了。但还差最后一步才能出发——**浏览器怎么知道要去哪台服务器?**小明输入的是
www.example.com,可网络世界里没有"名字",只有 IP 地址。本章回答两个问题:谁把域名翻译成 IP(DNS)?以及为什么有的页面加载飞快、有的慢吞吞——除了服务器远近,还有什么在起作用(CDN)?
本章要建立的认知
- DNS 是互联网的"电话簿":域名 → IP 的翻译靠一套分层的解析体系(递归 + 迭代),分层的意义是"每层只管自己的事";
- CDN 是"让旅程变短"的技术:静态资源(图片/JS/CSS)离用户越近越快——CDN 把内容复制到边缘节点,用户就近取;
- 两个技术都遵循同一个原则:业务没到,别先上——CDN 是阶段 2 用户增长之后才被逼出来的(第 2 章的"业务逼出技术")。
11.1 问路:域名到 IP
小明在地址栏输入 www.example.com,按下回车。浏览器做的第一件事是问路:这台服务器在哪?
没有 IP 地址,TCP 连接就建不起来,HTTP 报文更发不出去。DNS(Domain Name System,域名系统)就是互联网的"电话簿",负责把人类能读的域名翻译成机器能认的 IP 地址。
DNS 是"转圈"排查的第一站。 页面一直在转,先别急着怪服务器,确认一下"路问到了吗"。
一条命令就能定位:
nslookup www.example.com
# 或
dig www.example.com
看到解析结果和耗时,立刻就知道 DNS 是不是元凶。如果 nslookup 秒回但浏览器还是慢,问题在别处;如果 nslookup 本身就很慢,甚至超时,那瓶颈就在 DNS 这一环。
解析失败通常有三种形态:
- NXDOMAIN:域名不存在——打错字了,或者域名压根没配置解析
- 超时:权威服务器没响应——域名服务商出问题了
- 解析到错误 IP:域名被劫持——安全问题(见 11.3)
排查口诀:先问"查不查得到",再问"查到的是不是对的"。
解析过的域名,通常不会真的再去"问"。
浏览器查 DNS 是一条缓存链:浏览器缓存 → 操作系统缓存 → 本地 DNS 服务器。日常访问的绝大多数域名,在前两层就命中了,根本走不到公网。这也解释了为什么"改完 DNS 要等很久才生效"——服务器早改好了,是你本机的缓存还在说旧地址。
本地 DNS 也有兜底机制:操作系统通常配了主、备两个 DNS 服务器,一个没响应就换下一个。所以 DNS 挂了很少是"完全解析不了",更多是"变慢"——主 DNS 超时,等半天才切到备用的。
别把 DNS 想成一本大电话簿——它是一套分布式层级系统。
全球几亿个域名,每天无数次查询,任何单一"总电话簿"都会被查爆,而且单点故障会让全网瘫痪。所以 DNS 的设计是去中心化、分层级:根域名服务器 → 顶级域(.com)→ 权威域名服务器(example.com)→ 最终记录。没有中心节点,查询逐级扩散,各管一段。
这套结构还带来一个副作用:DNS 可以做最简单的负载均衡。一个域名可以配多个 A 记录(203.0.113.7 和 203.0.113.8),DNS 轮询返回不同 IP,用户就被分散到多台服务器。配合健康检查,挂掉的服务器还能从解析结果里摘除。DNS 轮询是负载均衡的原始形态,专业负载均衡器是它的进化版。
为什么非得用域名,直接写 IP 不行吗?
不行,两个根本理由。
第一,域名是稳定的名字,IP 是可换的地址。 服务器迁移、换云厂商、扩容加机器——IP 会变,但域名不变。用户和代码只认域名,底层 IP 换了不影响任何人,改一下 DNS 记录就行。代码里写死 IP 是反模式,服务器一迁就全线崩。
第二,域名是给人记的,IP 是给机器认的。 www.example.com 有语义,一眼就知道是什么服务;203.0.113.7 只是一串随机数字。人记名字、机器查地址,各取所需。这也解释了为什么好域名本身是资产——它是用户和产品之间的第一层品牌。
11.2 解析的旅程:递归与迭代
www.example.com 这个域名,从右往左读,像一棵倒长的树,每一层归不同的管理者管:
www.example.com
└── .com ← 顶级域(Top-Level Domain)
└── example ← 二级域(在 .com 下注册)
└── www ← 主机名(example.com 下的一台具体服务器)
顶级域分两类,混个脸熟就行:通用顶级域(gTLD)如 .com、.org、.net,全球通用;国家顶级域(ccTLD)如 .cn、.jp、.hk,按国家或地区分配。选哪个对技术实现影响不大,但背后的注册局不同——极端情况下(政策、合规),大公司会同时注册多个顶级域(example.com + example.cn)来规避风险。
域名层级对应 DNS 服务器的层级,每层只认自己那一截。 你的浏览器不直接认识 www.example.com,它只认识一个"本地 DNS"——通常是你路由器自动从运营商拿到的地址,也可能是你手动配的公共 DNS(如 8.8.8.8)。本地 DNS 的角色是"跑腿":你问它一个问题,它负责把答案找回来。
找答案的过程分两步,名字容易混,记住这个区分:
- 递归查询:浏览器 → 本地 DNS。浏览器把问题丢出去,等着拿最终答案,中间过程不管。
- 迭代查询:本地 DNS → 根 → 顶级域 → 权威服务器。本地 DNS 亲自一路问上去,每一层只给它指一下方向,它自己接着跑。
具体走法像问路:
- 浏览器问本地 DNS:"
www.example.com在哪?" - 本地 DNS 先问根服务器(
.)。根说:"我不认识www,但我知道.com归谁管,去问它。" - 本地 DNS 再问
.com服务器。.com说:"我不认识www,但我知道example.com归谁管,去问它。" - 本地 DNS 最后问
example.com的权威服务器。权威服务器说:"www在我这儿,IP 是203.0.113.7。" - 本地 DNS 把答案带回给浏览器。浏览器终于知道该去哪了。
根服务器只认顶级域,顶级域只认二级域,权威服务器才认识完整的主机名。 每层只负责自己那一截,不越界。这就是为什么 DNS 能撑住全球流量——没有中心节点,查询被分散到每一层,各管一摊。
本地 DNS 的质量直接决定你的上网体验。它的缓存热不热、离你是否够近、会不会被污染,都会影响解析速度和准确性。很多人把本地 DNS 从运营商默认改成公共 DNS(如 8.8.8.8 或 223.5.5.5),改的就是这个"跑腿人"的效率。
这段旅程里有三个关键设计,理解它们就理解了 DNS 为什么能撑住全球流量。
第一,递归和迭代各司其职。 浏览器只认识一个"本地 DNS",把问题丢给它就等着收答案——这叫递归,是"全权代办"。本地 DNS 收到问题后,亲自去问根、问顶级域、问权威服务器,每层只得到"下一步该找谁"的指引——这叫迭代,是"逐级问路"。浏览器不需要知道根服务器、.com 服务器在哪,它只需要信任本地 DNS 这一个入口。
第二,每层只认自己那一截。 根服务器不认识 example.com,它只认识 .com 的服务器在哪;.com 服务器不认识 www,它只认识 example.com 的权威服务器在哪。分层让每一层的表都很小——根服务器只需维护一千多个顶级域,用不着几亿个域名。没有中心节点,查询多走几跳,但任何一层倒下都只是局部影响,不会全网瘫痪。
第三,权威服务器才是"说了算"的。 只有 example.com 自己的权威服务器能给出 "www 在 203.0.113.7" 这个最终答案。其他层都是指路,只有它手里握着产权记录。域名本质上是租来的资产,租约存在权威服务器里,到期不续费,整个域名就在互联网上消失——注册商和权威服务器,两个环节都不能断。
本地 DNS 还有一个看不见的职责:缓存所有问过的答案。 你访问过 example.com,它就记下来,下次直接答,不用再走一遍迭代链。这就是为什么"换 DNS"能改变上网体验——缓存多、更新快、离得近的递归服务器,解析速度天差地别。排查时有个实用技巧:dig example.com 看本地解析,dig @8.8.8.8 example.com 看公共 DNS 解析,两条路答案不一致,就说明中间有人捣鬼(比如 DNS 劫持)。
一次"冷解析"(完全没缓存)大约要 20-100 毫秒;"热解析"(缓存命中)不到 1 毫秒。这个差距就是缓存存在的全部理由——DNS 的体验,本质上就是缓存的体验。
浏览器还有两个"预取"优化,把 DNS 时间提前花掉:dns-prefetch 提前解析将来要用的域名,preconnect 提前建立连接。原理和第 8 章的关键路径思维一样——把路上的时间挪到还没出发的时候消耗,真正请求时就能一路绿灯。
11.3 DNS 的代价与边界
DNS 让名字比 IP 好记,层级结构让全球几亿个域名都能各安其位。但它也有两面性——缓存带来延迟,开放带来攻击面。
缓存:快,但有保质期。
DNS 的每一层都会缓存答案(浏览器、操作系统、本地 DNS)。缓存让日常访问"秒查",但代价是更新延迟——服务器换了 IP,老缓存还在指旧地址。所以每条 DNS 记录都有 TTL(Time To Live),告诉缓存"多久后作废重查"。
TTL 设多长是个权衡:设 60 秒,更新快但查询频繁;设 86400 秒(一天),省资源但迁移后要等很久。运维老经验是:改记录前先降 TTL,改完验证后再调回去。 如果跳过这一步,全世界可能有一整天都在访问旧服务器——"一部分用户切过来了,一部分还在原地"的诡异现象,就是这么来的。
风险:DNS 是攻击者的首选入口。
网络不可靠是基本事实,而 DNS 是最容易被利用的一环。DNS 劫持(本地 DNS 或路由器被篡改,把 bank.example.com 指向攻击者的服务器)和 DNS 污染(中间设备篡改响应报文)是两种典型手段。
劫持最可怕的地方在于:地址栏显示的是对的,页面却是假的。 用户无从分辨。一个完整场景:小明的路由器被入侵,DNS 被改成攻击者的服务器;他访问网银,浏览器显示 bank.example.com,内容却是钓鱼页面;输入密码,账号直接被盗。
防御手段有两层:DNSSEC 给 DNS 记录加数字签名,验证"这个答案是真的"(思路和 HTTPS 证书链一样);DoH/DoT 把 DNS 查询本身加密,让中间设备看不见、改不了。但 DNSSEC 的部署率至今不高——要在权威服务器上配密钥、定期轮换,运维成本挡住了大多数站点。而 DoH 已经被 Chrome、Firefox 默认开启,浏览器自己走加密通道查询,绕过本地 DNS。这意味着用户侧的入口你越来越管不住,但你的权威服务器必须保证出口永远正确。
DNS 不只查 IP,记录类型要分清。
- A 记录:域名 → IPv4 地址,是"终点"
- AAAA 记录:域名 → IPv6 地址
- CNAME 记录:域名 → 另一个域名,是"别名"(CDN 调度常用)
- MX 记录:域名 → 邮件服务器
日常开发最常用 A 和 CNAME。CNAME 让"一个域名指向另一个域名"成为可能,省得每次换 IP 都改一堆记录。但泛解析(*.example.com)要小心——通配太宽会把不该解析的子域名也接住,是运维事故的常见来源。
一个轻量决策:DNS 服务器自建还是托管?
答案几乎总是托管(阿里云、Cloudflare 等)。托管免费、高可用、自带 DDoS 防护;自建要维护、要抗攻击、要把全世界的查询压力扛在自己肩上。DNS 是最不该自建的互联网基础设施之一——它的价值就在于"全世界都能查到"。
最后,域名资产管理记住三样:注册商(在哪租的)、续费日(到期不续就收回)、联络邮箱(很多域名被偷偷转移的事故,都是从邮箱被黑开始的)。三样都不能丢。
至于用户终端用哪家 DNS(运营商默认、公共 DNS 如 8.8.8.8、或浏览器自带的 DoH),这不是你能控制的。你能做的是:确保自己的权威服务器配置正确,无论查询从哪来,都能给出干净的答案。
11.4 CDN:让旅程变短
DNS 问题解决后,新的瓶颈浮现出来:静态资源加载慢。
案例的服务器在上海。上海用户打开页面很快,哈尔滨用户却很慢——因为物理距离就是延迟。光在光纤里每秒约 20 万公里,上海到哈尔滨往返 4000 公里,即便光速也要 20 毫秒以上,再加上路由器的排队和转发,实际往返延迟 40-60 毫秒。页面里有 50 个静态资源(图片、JS、CSS、字体),每个都要从上海拉,累积起来,哈尔滨用户的打开时间是上海用户的两三倍。
为什么偏偏是静态资源?
静态资源有个关键特性:内容不随用户变。小明的头像、卡片的样式、框架的 JS——今天加载和明天加载,内容一模一样。第 10 章说过,HTTP 的无状态让缓存成为可能,而静态资源正是缓存的完美对象:既然内容不变,为什么不把它复制到离用户近的地方,让用户就近取?
哈尔滨用户的体验很典型:页面文字先出来了(HTML 是动态的,必须走源服务器),但图片一张张转圈。第 8 章讲过 FCP(First Contentful Paint,第一个内容出现),这里的问题则落在另一个指标上——LCP(Largest Contentful Paint,最大内容出现)。网页的"最大内容"通常是图片,图片没到位,页面就"打开了但没完全打开"。
延迟拆开来是两件事:传播延迟(光在光纤里跑的时间,物理极限,没法优化)和排队延迟(路由器转发的等待,与网络拥塞有关)。第 10 章的 RTT 就是两者之和。传播延迟是物理极限,改不了;能改的只有路程——CDN 做的就是这件事:光速不变,那就把路变短。
静态和动态的边界要划清。
判断标准只有一条:同一个 URL,两个不同用户拿到的是否一样? 一样就是静态(图片、JS、CSS、字体、视频),可以缓存、可以复制到边缘;不一样就是动态(接口响应、个性化数据、购物车内容),不能缓存,必须回源。这个判断是 CDN 能不能加速的判决标准。
静态资源越"重",CDN 的价值越大——如果页面只有文字没有图,CDN 的意义就少一大半。图片(JPEG、PNG、WebP,体积差几倍)、JS/CSS(构建压缩后第 21 章讲)、字体(中文字体文件很大,是 CDN 重点对象)、视频(CDN 最重的负载)等,这些资源部署到 CDN 会节省很多用户等待时间。CDN(Content Delivery Network,内容分发网络)把静态内容复制到各地的边缘节点,用户请求时从最近的节点取。1998 年 Akamai 把这个思路产品化——内容先被推送到边缘,用户再从边缘拉取。二十多年过去,CDN 依然是静态资源分发的标准方案,说明它解决的是真实问题。
回到案例:当前阶段 1 只有一台服务器,静态资源和接口混在一起,这是合理的——用户还没变远,复杂度还没到位。但阶段 2 用户增长、地域分散后,CDN 将会从"可选"变成"必须"。
静态资源的完整链路还有一层缓存结构:浏览器缓存 → CDN 边缘节点 → 源服务器。浏览器先接住重复请求(第 10 章的 Cache-Control 控制),CDN 接住剩下的,源服务器只处理真正的漏网之鱼。每一级都是"命中就停,没命中才往下走"。
至此,网络段的三个角色齐了:HTTP 是路,DNS 是问路,CDN 是抄近道。三样东西合起来,才是"请求在网络段怎么走"的完整答案。
11.5 CDN 的工作原理
CDN 做两件事:调度(把用户送到最近的节点)和缓存(节点里存着内容)。
调度靠 DNS 的 CNAME。
你把静态资源的域名(比如 cdn.example.com)通过 CNAME 指向 CDN 厂商提供的域名。当用户请求这个地址时,CDN 的 DNS 服务器(也叫 GSLB,全局负载均衡)会根据用户的 IP 判断他在哪个区域,然后返回离他最近的边缘节点 IP。
普通 DNS 的答案是固定的,GSLB 的答案是因人而异的——哈尔滨用户拿到哈尔滨节点,上海用户拿到上海节点。为了调度灵活,CDN 域名的 TTL 通常设得很短(30-60 秒),这样节点故障时能快速切换,新节点上线也能立刻接客。
缓存靠"回源"。
用户请求到达边缘节点后,节点先问自己:我有这个文件吗?
- 命中:直接返回,通常只要 10-20 毫秒。
- 未命中:节点回源到源服务器取一份,存到本地,再返回给用户。下次同区域的用户再来,就命中了。回源一般要 100-200 毫秒,比命中慢一个量级。
所以 CDN 的性能逻辑就一句话:命中率越高,用户越快。 页面 50 个静态资源,全命中是"秒开",全回源是"转圈"。
提高命中率有三个常见手段:一是长 TTL(缓存久一点),二是版本化文件名(文件内容变了就换名字,旧缓存自然失效),三是活动前预热(主动把热点资源推上节点)。目标都是让命中成为常态,回源成为例外。
回源请求在源服务器看来,就是一次普通的 HTTP 请求。 CDN 节点替用户去取内容,源服务器正常响应即可。回源时也会带上第 10 章讲过的 Cache-Control 首部,边缘节点就靠它决定"这份内容在本地存多久"。如果源服务器响应里没带头,CDN 通常默认不缓存——排查"CDN 没生效",第一站先看源响应有没有 Cache-Control。
HTTPS 场景下,边缘节点也要有证书。 用户访问 https://cdn.example.com,证书要么由 CDN 厂商代管(你把证书上传给 CDN,它部署到所有节点),要么回源时再走一轮源服务器的 HTTPS。显然,让云厂商代管更省心——毕竟域名和证书的部署面从一台服务器变成了几十个节点。
静态和动态的分工边界在这里彻底划清。
图片、JS、CSS、字体——内容不变,走 CDN。接口响应、用户数据、个性化内容——因人而异,走源服务器。最佳实践是分域名:cdn.example.com 管静态,api.example.com 管接口。这样 CDN 只缓存该缓存的,不会误把动态接口也缓存了;同时还能绕过浏览器对单一域名的并发连接数限制。
把一次完整的 CDN 请求串起来,就是本章所有概念的协同:
用户访问 https://cdn.example.com/images/avatar.jpg → CNAME 指向 CDN 域名 → GSLB 根据用户位置返回最近节点 IP → HTTPS 验证节点证书 → 边缘节点查缓存(命中直接返回,未命中回源取货)→ Cache-Control 决定节点缓存多久。
一次请求,DNS、HTTP、HTTPS、CDN 全部在场——网络段的每个概念,都在真实请求里协同工作。
11.6 CDN 的代价与边界
CDN 的收益很直观,当然也有代价和边界。
第一,缓存一致性。
节点里的内容和源服务器可能不一致——源站更新了图片,边缘节点还存着旧的,直到 TTL 过期。解法有两个:主动刷新(源更新时通知 CDN 清缓存)和版本化文件名(更常用)。
版本化文件名是前端工程的标准做法。构建时给文件名加内容指纹,比如 avatar.a1b2c3.jpg,内容变了哈希就变,新文件自然对应新 URL。旧 URL 没人再访问,缓存跟着一起退休。缓存失效靠"换一个新名字"完成,旧内容不用删——这是最干净的缓存策略。
第二,动态内容不适合,且要花钱。
接口、个性化页面走 CDN 命中率极低,回源成本反而更高。CDN 不是万能加速器,只有静态内容才能抄近道。
成本方面,CDN 通常按流量计费。对小项目来说,流量费可能比省下的源站带宽还贵。所以"要不要上 CDN"是真实决策,不是跟风。
选择 CDN 服务时,可以走一遍轻量九步:节点覆盖(越密越好)、价格、HTTPS 支持(证书是否代管)、控制台体验。结论通常是"大厂够用,选价格和覆盖平衡的"。
内容来源两种模式:回源拉取(用户请求触发,省事)和主动推送(源站主动推到边缘,适合大促预热)。
阶段 1 为什么不上 CDN?
还是通过九步来判断要不要使用 CDN:业务目标是静态资源加速;约束是阶段 1 用户集中在上海周边,静态资源量小;候选方案 A 不上,B 上。评价维度:用户分布、资源占比、成本。结论:阶段 1 不上。 用户都在本地,CDN 的"就近"没有用武之地,反而增加配置和缓存管理成本。
演进条件写清楚:用户分布到全国时引入(阶段 2)。哈尔滨用户开始投诉"图片转圈"时,就需要引入 CDN 了,将静态资源迁到 CDN,CNAME 接入、分域名,可以把图片加载从 2 秒降到 300 毫秒。同时也会伴随新问题:缓存一致性、TTL 调优——每个技术都带来新代价。
CDN 的另一个作用:给源站挡流量。
用户请求打到边缘节点就结束,源站只承受回源流量。攻击者打 DDoS(第 19 章),打在 CDN 上,源站反而安全。CDN 是离用户最近的服务器,也是挡在源站前面的第一道墙。
故障模式也认识一下:边缘节点挂了,GSLB 自动把用户切到邻近健康节点;源站挂了,CDN 还能靠缓存撑一会儿,用户仍能拿到旧内容。"源站挂了但页面还能打开"——缓存成了意外的容灾。
11.7 本章对应表
| 业务诉求 | 技术选择 | 为什么 | 代价/取舍 |
|---|---|---|---|
| 名字要可记忆、能查 | DNS 分层解析(递归+迭代) | 层级让每层表小,无中心抗单点 | 多走几跳;缓存 TTL 与更新延迟 |
| 解析要快 | 各层缓存 + TTL | 缓存秒查,TTL 控制失效 | 更新延迟(改 DNS 先调低 TTL) |
| 解析要安全 | DNSSEC / DoH(初识) | 防劫持防污染 | 部署成本(第 19 章深化) |
| 静态资源加载慢 | CDN 就近缓存 | 物理距离决定延迟,就近抄近道 | 缓存一致性、动态内容不适合 |
| 用户去哪取 | DNS 调度(GSLB) | CDN 复用 DNS 做地理调度 | 调度精度依赖 DNS 准确性 |
| 要不要 CDN | 九步决策(阶段 1 不上) | 用户没分布到全国,没被逼出 | 阶段 2 用户增长才上(16 章接) |
DNS 分层解析让域名可记忆、可扩展,各层缓存加速但需权衡 TTL 与更新延迟,安全靠 DNSSEC/DoH 防劫持。静态资源用 CDN 就近分发,调度复用 DNS 的 GSLB,阶段 1 用户集中暂不上 CDN,待阶段 2 全国分布后再引入。
本章小结
- DNS 是互联网的"电话簿":域名 → IP 的翻译靠分层解析(递归 + 迭代),分层的意义是"每层只管自己的事";
- CDN 是"让旅程变短"的技术:静态内容复制到边缘节点,用户就近取——命中走捷径,未命中才回源;
- DNS 和 CDN 都遵循"业务逼出技术":CDN 是阶段 2 用户增长后才被逼出来的(第 16 章接上);
- CDN 还是"挡在源服务器前面的第一道墙"——第 24 章高可用会用到这个视角;
- 网络段(第 10、11 章)到此结束——下一站,请求终于到达服务器门口。
下一章
问路问完了(DNS),近道也知道了(CDN)——现在,请求真的到达了服务器:POST /v1/contents 的报文落在服务器上。服务器怎么接住它?谁先接待(框架的路由)?怎么把报文变成业务逻辑的调用(中间件、控制器)?业务规则又在哪里执行?这些问题的答案,都在旅程的下一站——服务器。
下一章,服务端:业务逻辑的家——请求到达服务器之后,整个后端是怎么组织起来的,从"谁先接待这个报文"开始讲起。