CDN 原理

广州用户的 3.2 秒

“光影”的 OSS 源站在北京。有一天我闲着没事,用 curl 测试了一下从不同地区访问同一张图片的延迟:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。
  • 请求验证关注返回状态、响应头、跳转目标和响应时间。

为什么差距这么大?因为光速

物理距离 + 网络跳数 + TCP 协议开销 = 远距离用户不可避免的延迟。

CDN 的核心思路很简单:既然不能缩短距离,就把数据搬到离用户更近的地方。

CDN 是怎么工作的?

一次完整的 CDN 访问流程:

用户在广州,输入 cdn.guangying.com


① DNS 解析
    用户 → Local DNS → 权威 DNS
    权威 DNS 返回:CNAME 到 CDN 的 DNS 域名
    CDN DNS 根据"广州"返回广州边缘节点的 IP


② 建立连接
    用户 → 广州边缘节点(物理距离 ~10km,RTT ~2ms)


③ 缓存查找
    广州边缘节点检查:这个 URL 有缓存吗?

    ├─ 有缓存 ──→ 直接返回 ✅(~5ms)

    └─ 无缓存 ──→ 回源到北京源站

                    ④ 回源请求
                    广州节点 → 北京源站(RTT ~40ms)
                    获取图片 → 缓存到广州节点 → 返回用户
                    总耗时:~100ms(第一次)
                    


⑤ 后续请求
    广州用户再次访问同一张图 → 广州边缘节点直接返回(~5ms)
    深圳用户访问同一张图 → 可能命中广州节点的缓存(~10ms)

DNS 解析的魔法

CDN 的关键在于 DNS 解析——它怎么知道用户在广州?

智能 DNS(GSLB)的判断依据:

判断"用户在哪里"的数据来源:

1. 用户 Local DNS 的 IP 地址
   → 精确到运营商 + 城市
   → 例如:119.29.xx.xx = 广东电信

2. EDNS Client Subnet(ECS)
   → 新版 DNS 协议,把用户真实 IP 传给权威 DNS
   → 比依赖 Local DNS IP 更准确

3. Anycast 路由
   → 同一个 IP 在全球多节点宣告
   → BGP 路由自动选择最近的节点

动手实验:接入 CDN

我在阿里云上开了一个 CDN 服务,把 cdn.guangying.com 指向 OSS 源站:

CDN 配好后,我重新测试了延迟:

验证要点

  • 命令只用于验证系统状态,读者不需要记具体参数。
  • 请求验证关注返回状态、响应头、跳转目标和响应时间。

效果对比

图片加载延迟对比(50KB WebP 缩略图)

地区     OSS 直连      CDN(首次)    CDN(命中)   提升
────────────────────────────────────────────────────────
北京      62ms          55ms          5ms          12倍
上海      180ms         90ms          8ms          22倍
广州      3200ms        120ms         10ms         320倍
成都      2800ms        100ms         8ms          350倍
纽约      8500ms        500ms         30ms         283倍

缓存命中后,所有地区都在 10~30ms 内完成。

回源策略

缓存不会永远存在。当缓存过期或被淘汰时,CDN 节点需要回到源站获取图片。

回源优化:回源跟随 301

CDN 缓存命中率

缓存命中率是 CDN 的核心指标:

CDN 的成本

等等——CDN 流量费比 OSS 直连还贵?是的,CDN 本身不省钱,它省的是用户体验

但 CDN 间接省钱的地方在于:

  1. 回源流量减少 95%——OSS 外网流量费大幅降低
  2. 源站压力减少——不需要高配置服务器
  3. 用户留存提升——加载速度影响转化率