Skip to content

CDN 与全球加速

从"为什么我的网站在国外打开这么慢"出发,全面拆解 CDN 的核心原理、缓存策略、回源机制、边缘计算能力——让你从"会用 CDN"到"能调好 CDN",覆盖静态资源分发、动态加速、HTTPS 优化和成本控制。


1. 为什么需要 CDN

你在上海访问自己部署在上海的网站,200ms 加载完成。然后给一个美国朋友看——他等了 3 秒还没打开。同样的服务器、同样的代码、同样的带宽——唯一的区别是距离。这一章解释为什么"距离"会让 Web 体验天差地别,以及 CDN 是怎么解决这个问题的。

1.1 距离的代价:一个 HTTP 请求的旅程

光速不是无限的。

上海 → 洛杉矶,光纤直线距离约 10,500 km

光在光纤中的传播速度 ≈ 光速的 2/3 ≈ 200,000 km/s
单程延迟 = 10,500 / 200,000 = 52.5ms

但网络请求是"请求 + 响应"——一个往返(RTT):
RTT = 52.5ms × 2 = 105ms

这只是"光跑一个来回"的理论最优值。
真实网络还有路由器跳转、排队、拥塞……
实测 RTT 通常是理论值的 1.5-3 倍:
→ 上海 ↔ 洛杉矶实测 RTT ≈ 150-200ms

一次 HTTPS 请求需要多少个 RTT?

加载一个 HTTPS 页面需要经历:

  1. DNS 解析          1 RTT  (问 DNS 服务器这个域名的 IP)
  2. TCP 三次握手      1 RTT  (SYN → SYN-ACK → ACK)
  3. TLS 握手          2 RTT  (TLS 1.2) 或 1 RTT (TLS 1.3)
  4. HTTP 请求/响应    1 RTT  (发请求 → 收到第一个字节)
  ─────────────────────────
  总计                 5 RTT  (TLS 1.2) 或 4 RTT (TLS 1.3)

上海 → 洛杉矶(RTT ≈ 180ms):
  → 首字节到达 = 180ms × 5 = 900ms(TLS 1.2)
  → 加上页面需要加载 CSS/JS/图片(又要多次请求)
  → 实际体感:2-4 秒

上海 → 上海(RTT ≈ 5ms):
  → 首字节到达 = 5ms × 5 = 25ms
  → 实际体感:200ms

同一个网站,距离不同,体验差 10 倍以上。

各地到源站的延迟对比(源站在上海):

用户位置与源站距离实测 RTT首字节时间(TTFB)体感加载
上海本地0 km~5ms~25ms极快
北京~1,100 km~30ms~150ms
香港~1,500 km~40ms~200ms
新加坡~3,800 km~70ms~350ms可以接受
东京~1,800 km~50ms~250ms可以接受
洛杉矶~10,500 km~180ms~900ms明显等待
伦敦~9,200 km~250ms~1,250ms
圣保罗~18,000 km~350ms~1,750ms很慢

💡 物理距离是 Web 性能的"隐形杀手"。你可以把服务器 CPU 从 4 核升到 64 核、把数据库查询从 100ms 优化到 1ms——但如果用户在地球另一边,光速限制的 RTT 你完全无法优化。唯一的解决办法是:把内容放到离用户更近的地方

1.2 CDN 的核心思路:把内容搬到用户身边

既然"距离"是问题根源,解决方案也很直觉:在全球各地放服务器,把内容提前复制过去,让用户从最近的服务器获取。这就是 CDN(Content Delivery Network,内容分发网络)。

没有 CDN 的世界:
═══════════════════════════════════════════
  巴西用户                    源站(上海)
  ────── 18,000 km ──────────▶ 🖥️
  RTT: 350ms × 5 = 1,750ms
  体感:慢得想关掉

有 CDN 的世界:
═══════════════════════════════════════════
  巴西用户     圣保罗 CDN 节点        源站(上海)
  ── 50km ──▶  📦 有缓存?直接返回!
               📦 没缓存?→ 回源站拿,缓存后给用户
  
  RTT: 5ms × 5 = 25ms(命中缓存时)
  体感:和访问本地网站一样快

CDN 的工作流程(简化版):

用户访问 https://static.example.com/logo.png

  Step 1: DNS 解析
  ════════════════
  static.example.com → CNAME → cdn.provider.com
  → CDN 的智能 DNS 返回离用户最近的边缘节点 IP
  
  Step 2: 请求到达边缘节点
  ════════════════
  用户 → 最近的 CDN 节点(比如圣保罗节点)
  
  Step 3: 缓存命中?
  ════════════════
  缓存命中(HIT)→ 直接返回文件,完成!✅
  缓存未命中(MISS)→ 进入 Step 4
  
  Step 4: 回源
  ════════════════
  CDN 节点 → 源站(上海):请求 /logo.png
  源站返回文件
  CDN 节点缓存一份,然后返回给用户
  → 下一个巴西用户再请求这个文件时就是 HIT 了

CDN 能加速什么?

内容类型CDN 效果原因
图片/视频/字体⭐⭐⭐⭐⭐ 极佳完全静态、缓存命中率极高
CSS / JS 文件⭐⭐⭐⭐⭐ 极佳静态文件、哈希命名后可永久缓存
HTML 页面⭐⭐⭐ 较好可缓存但 TTL 较短(内容可能变化)
API 接口⭐⭐ 一般动态内容不能缓存内容本身,但可以优化传输路径
WebSocket⭐ 有限长连接,CDN 主要做路由优化
数据库查询❌ 不适用CDN 不处理应用层逻辑

💡 CDN 的本质是"用空间换时间"——在全球各地用存储空间缓存内容(花更多的存储成本),换来用户访问时的低延迟(节省大量时间)。和 Redis 缓存思路一模一样,只不过 CDN 是在地理维度上做缓存。

1.3 CDN vs 自建多机房 vs 云厂商加速——什么时候该用 CDN

"把内容搬近用户"有多种方案,CDN 只是其中之一。选错方案,要么花冤枉钱,要么解决不了问题。

方案 1:CDN(内容分发网络)
═══════════════════════════════════════════
  原理:第三方在全球有上千个节点,缓存你的静态内容
  成本:按流量/带宽计费,起步很低
  适用:静态资源(图片/CSS/JS/视频)
  不适用:需要实时数据的动态 API
  落地难度:★☆☆☆☆(改个 DNS 就行)

方案 2:自建多机房
═══════════════════════════════════════════
  原理:在多个地区部署完整的服务器集群
  成本:每个机房都要服务器 + 运维 + 数据同步
  适用:对延迟极度敏感的业务(游戏、金融交易)
  不适用:小团队、流量不大的应用
  落地难度:★★★★★(数据同步是噩梦)

方案 3:云厂商全球加速
═══════════════════════════════════════════
  原理:利用云厂商的骨干网传输,不走公网
  典型产品:AWS Global Accelerator / 阿里云全站加速
  成本:按流量 + 固定费,中等
  适用:动态 API 也需要加速的场景
  落地难度:★★☆☆☆(配置产品即可)

三种方案对比:

维度CDN自建多机房云厂商全球加速
初始成本低(甚至免费)极高中等
月费(中等流量)¥100-2,000¥50,000+¥2,000-10,000
静态加速⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
动态加速⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
落地难度极低极高
团队要求无需专人需要运维团队无需专人
典型用户所有网站大厂、游戏出海 SaaS

务实建议:

你应该用哪种方案?

  90% 的网站 → CDN 就够了
  ══════════════════════════
  你的网站有图片、CSS、JS、视频
  → 上 CDN,改个 DNS 记录,立刻见效
  → 免费方案(Cloudflare)也够用
  
  出海 SaaS / API 服务 → CDN + 全站加速
  ══════════════════════════
  你的用户在全球,API 也需要低延迟
  → 静态资源走 CDN
  → API 走全站加速(DCDN / Global Accelerator)
  
  游戏 / 金融 / 超低延迟 → 自建 + CDN
  ══════════════════════════
  你对延迟极度敏感(< 50ms)
  → 核心业务自建多区域部署
  → 静态资源仍然用 CDN
  
  个人博客 / 小项目 → Cloudflare 免费套餐
  ══════════════════════════
  不花一分钱就能获得 CDN + DNS + DDoS 防护 + HTTPS
  → 没有理由不用

💡 CDN 是投入产出比最高的性能优化手段——花 5 分钟配置一个 DNS CNAME 记录,就能让全球用户的访问速度提升数倍。没有其他任何优化能在这么短时间内产生如此大的效果。如果你的网站还没用 CDN,现在就去配。

第 1 章核心知识回顾:

概念一句话解释
RTT往返延迟,物理距离越远 RTT 越大,光速无法突破
TTFB首字节到达时间 ≈ RTT × 握手轮数,直接决定体感速度
CDN在全球部署缓存节点,让用户就近获取内容
缓存命中CDN 节点有缓存直接返回(HIT),没有则回源(MISS)
选型建议90% 场景 CDN 就够,出海 SaaS 加全站加速,超低延迟自建

2. CDN 架构全景

第 1 章知道了"CDN 在全球放节点"——但这些节点不是扁平的,它们有层级。理解 CDN 的三层架构和 DNS 调度机制,你才能真正理解缓存为什么没命中、回源为什么慢、节点为什么选"错"了。

2.1 三层架构:边缘节点 → 中间层 → 源站

CDN 不是"把你的文件复制到全球每一个节点"——那样太浪费空间了。它是三层金字塔结构,越靠近用户的层节点越多但缓存越少,越靠近源站的层节点越少但缓存越全。

CDN 三层架构:

  ┌─────────────────────────────────────────────────┐
  │              Layer 3: 源站(Origin)              │
  │  你的服务器(Nginx / S3 / OSS)                   │
  │  全量内容,唯一的数据真相来源                       │
  │  全球只有 1-2 个                                  │
  └──────────────────────┬──────────────────────────┘
                         │ 回源请求(MISS 时)
  ┌──────────────────────▼──────────────────────────┐
  │        Layer 2: 中间层(Mid-tier / Shield)       │
  │  区域级缓存节点(每个大洲 1-3 个)                  │
  │  缓存较热的内容,减少回源次数                       │
  │  全球约 10-30 个                                  │
  └────┬─────────────┬──────────────┬───────────────┘
       │             │              │
  ┌────▼───┐   ┌────▼───┐   ┌─────▼──┐
  │ Edge   │   │ Edge   │   │ Edge   │  Layer 1: 边缘节点
  │ 上海   │   │ 东京   │   │ 圣保罗 │  离用户最近
  │ POP    │   │ POP    │   │ POP    │  全球数百到数千个
  └────────┘   └────────┘   └────────┘
       ▲             ▲              ▲
     用户A         用户B          用户C

各层的职责和处理逻辑:

边缘节点(Edge / POP)
═══════════════════════════════════
  位置:各大城市的电信机房(离用户最近,通常 < 50km)
  数量:数百到数千个(Cloudflare 有 300+ 个城市节点)
  缓存:只缓存最热的内容(存储空间有限)
  逻辑:
    收到请求 → 本地有缓存?
      HIT  → 直接返回(最快,1-10ms)
      MISS → 不直接回源!转发给中间层

中间层(Mid-tier / Origin Shield)
═══════════════════════════════════
  位置:区域数据中心(每个大洲 1-3 个)
  数量:10-30 个
  缓存:缓存大部分热门内容(存储空间比边缘大得多)
  逻辑:
    收到边缘节点的请求 → 本地有缓存?
      HIT  → 返回给边缘节点(较快,10-50ms)
      MISS → 回源站拿

源站(Origin)
═══════════════════════════════════
  位置:你的服务器所在地
  数量:通常 1 个(可配主备)
  内容:全量数据的唯一来源
  逻辑:收到请求 → 返回文件

为什么需要中间层?(不能边缘直接回源吗?)

没有中间层的问题:
═══════════════════════════════════
  源站在上海
  全球 500 个边缘节点
  → 一个冷门文件被 10 个不同城市的用户请求
  → 500 个边缘节点中有 10 个同时回源
  → 源站收到 10 次相同请求(回源放大)
  → 热门文件可能触发数百次回源!

有中间层的好处:
═══════════════════════════════════
  10 个边缘节点 MISS → 都转发给同一个区域的中间层
  → 中间层只回源 1 次,缓存后返回给 10 个边缘
  → 源站只承受 1 次请求
  → 回源请求减少 90%+

💡 中间层是"源站的保护伞"。没有中间层,源站会被全球数百个边缘节点的回源请求淹没。这也是为什么配置 CDN 时你会看到"Origin Shield"选项——它就是中间层,值得开启。

2.2 DNS 调度:用户的请求如何路由到最近的节点

CDN 最关键的技术问题是:用户访问你的域名时,怎么"找到"离他最近的 CDN 节点? 答案是 DNS。

CNAME 跳转——CDN 接入的核心机制:

你的域名接入 CDN 的过程:

  原来的 DNS 配置:
    static.example.com → A 记录 → 1.2.3.4(你的源站 IP)

  改为 CNAME 后:
    static.example.com → CNAME → static.example.com.cdn.provider.com
    → DNS 解析权交给了 CDN 厂商!
    → CDN 的 DNS 根据用户位置返回最近的边缘节点 IP

完整的 DNS 解析链路:

用户在巴西圣保罗,访问 static.example.com/logo.png

  1. 浏览器 → 本地 DNS 缓存(有缓存就直接用,跳到第 6 步)

  2. 本地 DNS → 递归 DNS 服务器(运营商的 DNS)
     "static.example.com 的 IP 是什么?"
  
  3. 递归 DNS → example.com 的权威 DNS
     返回:CNAME static.example.com.cdn.provider.com
     "去问 CDN 厂商的 DNS"
  
  4. 递归 DNS → CDN 厂商的智能 DNS
     CDN DNS 做三件事:
     ┌─────────────────────────────────────┐
     │ ① 判断用户位置:巴西圣保罗           │
     │ ② 查看各节点健康状态和负载           │
     │ ③ 返回最近且可用的边缘节点 IP        │
     └─────────────────────────────────────┘
     返回:203.0.113.100(圣保罗 POP 节点 IP)
  
  5. 递归 DNS → 浏览器
     "static.example.com 的 IP 是 203.0.113.100"
  
  6. 浏览器 → 203.0.113.100(圣保罗 CDN 节点)
     请求 /logo.png

CDN 智能 DNS 怎么知道"用户在哪"?

判断依据(按优先级):

  ① 递归 DNS 的 IP 地址
  ═══════════════════════════════════
  用户的 DNS 请求经过运营商的递归 DNS
  → CDN 通过递归 DNS 的 IP 判断用户大致位置
  → 问题:用户用了 8.8.8.8(Google DNS),位置可能不准

  ② EDNS Client Subnet (ECS)
  ═══════════════════════════════════
  DNS 协议扩展,递归 DNS 附带用户子网信息
  → CDN 能更准确地知道用户位置
  → Google DNS / Cloudflare DNS 都支持
  → 这是现代 CDN 调度精准的关键

  ③ 运营商 + 地域综合判断
  ═══════════════════════════════════
  同一个城市,电信和联通用户应该去不同的节点
  → CDN 维护 IP → 运营商 的映射库
  → 电信用户 → 电信机房的节点
  → 联通用户 → 联通机房的节点

💡 DNS 调度是 CDN 的"大脑"——调度得好,用户访问最近的节点,体验极佳;调度得差,中国电信的用户可能被分配到联通节点(跨运营商延迟大),或者本该去上海的用户被分配到广州。这也是为什么大厂 CDN(Cloudflare、阿里云)比小厂好的核心原因之一——调度准确度差距巨大。

2.3 Anycast vs GeoDNS vs HTTP 302 调度——三种路由策略对比

DNS 调度不是唯一方案。CDN 行业有三种主流路由策略,各有适用场景:

策略 1: GeoDNS(地理 DNS 调度)
═══════════════════════════════════
  原理:CDN 的 DNS 服务器根据用户 IP 的地理位置,
        返回不同地区的边缘节点 IP
  
  优点:✅ 实现简单、技术成熟
        ✅ 可以精确到运营商级别(电信→电信节点)
  缺点:❌ 依赖 DNS 缓存 TTL(切换节点有延迟)
        ❌ 用户用了公共 DNS(8.8.8.8)可能判断不准
  代表:阿里云 CDN、腾讯云 CDN、AWS CloudFront


策略 2: Anycast(任播路由)
═══════════════════════════════════
  原理:全球多个节点宣告相同的 IP 地址,
        BGP 路由协议自动把请求路由到最近的节点
  
  优点:✅ 天然选择最近节点(网络层级别,无需 DNS 判断)
        ✅ 节点故障自动切换(BGP 撤回路由即可)
        ✅ 天然抗 DDoS(攻击流量被分散到全球节点)
  缺点:❌ 需要控制 BGP 路由(门槛高)
        ❌ "最近" 是网络距离,不一定是地理最近
        ❌ 不能做运营商级别的精细调度
  代表:Cloudflare(全 Anycast 架构)、Google Cloud CDN


策略 3: HTTP 302 调度
═══════════════════════════════════
  原理:用户先请求一个调度服务器,
        调度服务器返回 302 重定向到最优节点
  
  优点:✅ 调度精度最高(可根据实时负载、用户 IP 精确判断)
        ✅ 不受 DNS 缓存影响(每次请求都重新调度)
  缺点:❌ 多一次 HTTP 往返(增加 ~1 个 RTT)
        ❌ 实现复杂
  代表:部分点播/直播 CDN、大文件下载场景

三种策略对比表:

维度GeoDNSAnycastHTTP 302
调度层级DNS 层网络层(BGP)应用层(HTTP)
精准度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
切换速度受 TTL 限制秒级(BGP 收敛)实时
额外延迟+1 RTT
抗 DDoS一般⭐⭐⭐⭐⭐(天然)一般
落地难度高(需 BGP 能力)
典型场景国内 CDN全球 CDN视频/大文件
实际使用中,大多数 CDN 厂商混合使用多种策略:

  Cloudflare = Anycast(主) + GeoDNS(辅)
  阿里云 CDN = GeoDNS(主) + 302 调度(视频场景)
  AWS CloudFront = GeoDNS + Anycast(部分节点)

→ 你不需要自己选策略——CDN 厂商帮你做了
→ 你需要关注的是:调度结果对不对(第 9 章教你怎么测)

💡 作为 CDN 用户,你不需要实现调度策略——这是 CDN 厂商的核心竞争力。你需要知道的是:① Cloudflare 用 Anycast,天然抗 DDoS,适合全球业务;② 阿里云用 GeoDNS,国内调度精准,适合国内业务;③ 如果发现某些地区加速效果差,很可能是调度不准——这时候要找 CDN 厂商调整。

第 2 章核心知识回顾:

概念一句话解释
三层架构边缘节点(离用户近)→ 中间层(区域缓存)→ 源站(数据来源)
中间层聚合回源请求,保护源站不被回源洪水击垮
CNAME 接入把域名 CNAME 到 CDN,DNS 解析权交给 CDN 厂商
GeoDNS根据用户 IP 地理位置返回最近节点,国内 CDN 主流
Anycast多节点同一 IP,BGP 自动路由到最近节点,Cloudflare 主流

3. 缓存策略:CDN 的灵魂

CDN 的价值 = 缓存命中率。命中率 95% 意味着每 100 个请求只有 5 个需要回源——源站压力极低、用户体验极好。命中率 30% 意味着 70 个请求都要回源——CDN 就是个贵的反向代理,白花钱。

💡 本章目标:彻底理解 HTTP 缓存机制 + CDN 缓存配置 + 缓存 Key 设计 + 命中率优化四板斧。

3.1 HTTP 缓存机制回顾:Cache-Control / ETag / Last-Modified

CDN 的缓存行为建立在 HTTP 缓存协议之上——不理解 HTTP 缓存头,就无法正确配置 CDN。

强缓存 vs 协商缓存:

HTTP 缓存两大类:

  强缓存(直接用,不问服务器)
  ═══════════════════════════════════
  浏览器/CDN 看到 Cache-Control: max-age=86400
  → 文件在本地缓存 86400 秒(1 天)
  → 1 天内再请求这个文件?直接用缓存,不发任何请求!
  → 状态码:200 (from cache)
  
  协商缓存(先问服务器"变没变")
  ═══════════════════════════════════
  缓存过期后,浏览器/CDN 发条件请求:
  → If-None-Match: "abc123"(带上 ETag)
  → 服务器检查:文件变了吗?
    → 没变 → 返回 304 Not Modified(不传内容,省带宽)
    → 变了 → 返回 200 + 新内容

Cache-Control 指令详解:

Cache-Control 是控制缓存的核心 Header:

  max-age=<秒数>
  ═══════════════════════════════════
  Cache-Control: max-age=31536000  (1 年)
  → CDN 和浏览器都可以缓存,持续 1 年
  → 适合:带哈希的静态资源(logo.a1b2c3.js)

  s-maxage=<秒数>
  ═══════════════════════════════════
  Cache-Control: s-maxage=600, max-age=60
  → CDN(共享缓存)缓存 600 秒
  → 浏览器(私有缓存)只缓存 60 秒
  → 适合:需要 CDN 灵活控制的场景

  no-cache
  ═══════════════════════════════════
  Cache-Control: no-cache
  → 不是"不缓存"!是"每次必须向服务器验证"
  → 实际效果:走协商缓存(304)
  → 适合:HTML 页面(可缓存但需要及时更新)

  no-store
  ═══════════════════════════════════
  Cache-Control: no-store
  → 真正的"不缓存"——CDN 和浏览器都不存
  → 适合:登录接口、支付页面等敏感内容

  public / private
  ═══════════════════════════════════
  public  → CDN 可以缓存(共享缓存)
  private → 只有浏览器能缓存,CDN 不缓存
  → 适合:private 用于包含用户个人数据的响应

ETag 和 Last-Modified——协商缓存的两种方式:

机制请求 Header响应 Header精度
ETagIf-None-Match: "abc123"ETag: "abc123"字节级(精确)
Last-ModifiedIf-Modified-Since: Wed, 15 Jan...Last-Modified: Wed, 15 Jan...秒级(可能不准)
完整的缓存判断流程:

  请求到达 CDN 节点


  本地有缓存?── No ──→ 回源获取,缓存一份,返回

      Yes


  缓存过期了?── No ──→ 直接返回缓存(HIT,最快)

      Yes


  发条件请求给源站(带 ETag / If-Modified-Since)

       ├── 304 Not Modified → 刷新缓存 TTL,返回缓存内容

       └── 200 OK + 新内容 → 更新缓存,返回新内容

💡 对于 CDN 场景,s-maxage 是最重要的指令——它让你可以独立控制 CDN 和浏览器的缓存时长。典型配置:CDN 缓存 1 小时(s-maxage=3600),浏览器缓存 5 分钟(max-age=300)。这样 CDN 命中率高,同时浏览器端更新也不会太慢。

3.2 CDN 缓存规则配置:路径匹配、文件类型、自定义 TTL

源站的 Cache-Control 是"建议",CDN 可以选择遵守或覆盖。大多数 CDN 控制台允许你配置自己的缓存规则——CDN 规则的优先级 > 源站 Header

CDN 缓存规则的三种匹配方式:

方式 1:按文件扩展名匹配
═══════════════════════════════════
  .jpg / .png / .gif / .webp  → 缓存 30 天
  .css / .js                  → 缓存 7 天
  .html                       → 缓存 10 分钟
  .json / .xml                → 不缓存

方式 2:按 URL 路径匹配
═══════════════════════════════════
  /static/*                   → 缓存 1 年
  /api/*                      → 不缓存
  /assets/images/*             → 缓存 30 天
  /                           → 缓存 5 分钟

方式 3:按完整 URL 匹配
═══════════════════════════════════
  /index.html                 → 缓存 5 分钟
  /sitemap.xml                → 缓存 1 小时
  /robots.txt                 → 缓存 1 天

生产环境推荐的缓存 TTL 模板:

资源类型缓存时长原因
带哈希的 JS/CSS(app.a1b2c3.js1 年(31536000s)文件名含哈希,内容变 = 文件名变
图片/字体/视频30 天不常变化
HTML 页面5-10 分钟需要较快更新
favicon.ico7 天极少变化
API 接口0(不缓存)动态内容
用户上传内容7 天上传后很少修改

Nginx 源站配置示例(配合 CDN):

nginx
# 带哈希的静态资源——永久缓存
location ~* \.(js|css)$ {
    # 文件名包含哈希时使用
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# 图片——长缓存
location ~* \.(jpg|jpeg|png|gif|webp|svg|ico)$ {
    add_header Cache-Control "public, max-age=2592000";  # 30 天
}

# HTML——短缓存 + CDN 独立控制
location ~* \.html$ {
    add_header Cache-Control "public, s-maxage=600, max-age=300";
    # CDN 缓存 10 分钟,浏览器缓存 5 分钟
}

# API——不缓存
location /api/ {
    add_header Cache-Control "no-store";
}

💡 immutable 是一个被低估的指令Cache-Control: immutable 告诉浏览器"这个文件永远不会变"——用户刷新页面时,浏览器不会发协商请求(连 304 都省了)。对于带哈希的静态资源,加上 immutable 能消除不必要的 304 请求。

3.3 缓存 Key 设计:忽略参数、Header 变体、Cookie 分区

缓存 Key 是 CDN 用来查找缓存的"索引"。Key 设计不好,同样的文件被当成不同的缓存条目——命中率暴跌。

什么是缓存 Key?

默认的缓存 Key = URL 全路径(包括查询参数)

  请求 1: /logo.png?v=1        → Key: /logo.png?v=1  → MISS → 缓存
  请求 2: /logo.png?v=2        → Key: /logo.png?v=2  → MISS → 又缓存一份!
  请求 3: /logo.png?from=home  → Key: /logo.png?from=home → MISS → 又缓存一份!

  → 同一个文件,3 个不同的缓存条目
  → 命中率:0%(因为没人请求完全相同的 URL)

问题 1:URL 参数导致缓存分裂

典型场景:营销追踪参数

  /product.html?utm_source=google
  /product.html?utm_source=twitter
  /product.html?utm_source=email
  /product.html?fbclid=abc123
  /product.html?ref=partner

  → 5 个 URL,内容完全一样
  → 但 CDN 认为是 5 个不同的资源
  → 缓存命中率直接腰斩

解决方案:配置 CDN 忽略指定参数
  → 忽略 utm_*, fbclid, ref, from 等追踪参数
  → 缓存 Key 只用 /product.html
  → 5 个请求命中同一份缓存

问题 2:Vary Header 的坑

Vary Header 告诉 CDN:"不同的请求头值 = 不同的缓存"

  响应头:Vary: Accept-Encoding
  → 合理!gzip 和 br 压缩版本确实不同
  → CDN 缓存两份:一份 gzip,一份 brotli

  响应头:Vary: User-Agent
  → 灾难!User-Agent 有几千种不同值
  → 相当于每种浏览器版本一份缓存
  → 命中率 → 趋近于 0%

  响应头:Vary: Cookie
  → 更大的灾难!每个用户 Cookie 都不同
  → 相当于不缓存

安全的 Vary 值:
  ✅ Accept-Encoding(gzip/br 变体)
  ✅ Accept(HTML vs JSON 内容协商)
  ❌ User-Agent、Cookie、Authorization

问题 3:Cookie 对缓存的影响

很多源站的响应默认带 Set-Cookie:

  响应头:Set-Cookie: session_id=abc123

  CDN 看到 Set-Cookie 后的行为(各厂商不同):
  → Cloudflare:默认不缓存带 Set-Cookie 的响应
  → 阿里云 CDN:可配置是否忽略 Cookie
  → AWS CloudFront:默认不缓存

解决方案:
  ① 静态资源的响应不要带 Set-Cookie
  ② 用独立域名(static.example.com)提供静态资源
  ③ CDN 配置中忽略 Cookie

💡 忽略无关的 URL 参数和 Cookie 是提升命中率最立竿见影的操作——很多网站的命中率从 40% 直接跳到 80%+,只是因为做了这一件事。配 CDN 后第一件事就检查:你的请求 URL 上有没有追踪参数?源站响应有没有带 Set-Cookie?

3.4 缓存命中率优化:从 60% 到 95% 的实战技巧

把前面三节的知识汇总,这是一份缓存命中率优化清单——从最容易做到的开始:

优化 1:静态资源用独立域名(立刻做)
═══════════════════════════════════
  ❌ example.com/images/logo.png     ← 主域名,请求会带 Cookie
  ✅ static.example.com/logo.png     ← 独立域名,无 Cookie 污染

  效果:命中率 +10-20%(消除 Cookie 导致的缓存失效)


优化 2:静态资源文件名加哈希(构建工具自动做)
═══════════════════════════════════
  ❌ /js/app.js                      ← 文件名不变,TTL 不敢设太长
  ✅ /js/app.a1b2c3d4.js             ← 内容变 → 哈希变 → 文件名变

  效果:TTL 可以设 1 年,命中率 +20%


优化 3:忽略无关 URL 参数(CDN 控制台配置)
═══════════════════════════════════
  忽略列表:utm_source, utm_medium, utm_campaign,
           fbclid, gclid, ref, from, _t, timestamp

  效果:命中率 +10-30%(取决于你的 URL 参数多不多)


优化 4:内容预热(大促 / 发布前做)
═══════════════════════════════════
  CDN 默认是"被动缓存"——第一个请求一定是 MISS
  预热 = 主动把内容推到 CDN 节点

  方式 1:CDN 控制台提交预热任务
  方式 2:脚本批量 curl 所有静态资源 URL
  方式 3:Cloudflare API 批量预热

  效果:消除"冷启动"导致的 MISS,大促不卡


优化 5:合理设置 TTL(不要一刀切)
═══════════════════════════════════
  不变的资源(带哈希的 JS/CSS)→ 1 年
  很少变的资源(图片/字体)    → 30 天
  偶尔变的资源(HTML)         → 10 分钟
  频繁变的资源(API)          → 不缓存

  效果:命中率 +5-10%


优化 6:消除 Vary 头污染(检查源站配置)
═══════════════════════════════════
  检查:curl -I https://static.example.com/logo.png
  看 Vary 头的值——只允许 Accept-Encoding

  效果:命中率 +5-15%(看 Vary 头有多"脏")

优化前后对比:

指标优化前优化后
缓存命中率40-60%90-98%
回源带宽100 Mbps5-15 Mbps
源站 QPS5,000200-500
用户 TTFB200-500ms10-50ms
CDN 月费¥2,000(回源流量大)¥800(回源少)

💡 缓存命中率是 CDN 的核心 KPI。90% 以下说明有配置问题,95%+ 是健康的标准。做完上面 6 项优化,大多数网站都能到 95%+。如果还上不去,检查是不是有"长尾冷内容"太多(文件总量大但每个文件访问量低)——这种情况考虑合并小文件或开启中间层缓存。

第 3 章核心知识回顾:

概念一句话解释
强缓存max-age 未过期时直接用缓存,不发请求
协商缓存过期后发条件请求(ETag/304),确认没变就继续用
s-maxage独立控制 CDN 缓存时长,不影响浏览器
缓存 KeyCDN 查找缓存的索引,默认是完整 URL(含参数)
命中率优化独立域名 + 哈希命名 + 忽略参数 + 预热 + TTL + Vary

4. 回源机制与源站保护

缓存没命中的时候,CDN 要回源站拿内容——这个过程叫"回源"。回源是 CDN 系统中延迟最高、风险最大的环节:回源慢用户就等得久,回源请求太多源站就被打爆。

4.1 回源流程拆解:什么时候 CDN 要找源站要内容

CDN 触发回源的四种场景:

  场景 1:首次请求(Cold MISS)
  ═══════════════════════════════════
  一个全新的 URL 从未被 CDN 缓存过
  → 第一个用户请求一定是 MISS → 回源
  → 解决:预热(提前把内容推到 CDN)

  场景 2:缓存过期(TTL Expired)
  ═══════════════════════════════════
  缓存已经存在,但 TTL 到期了
  → CDN 发协商请求:If-None-Match / If-Modified-Since
  → 源站没变 → 304(不传内容,只刷新 TTL)
  → 源站变了 → 200 + 新内容
  → 解决:设置合理的 TTL

  场景 3:缓存被淘汰(Eviction)
  ═══════════════════════════════════
  边缘节点磁盘满了,LRU 淘汰最久未访问的缓存
  → 冷门文件被淘汰后再被请求 → MISS → 回源
  → 解决:开启中间层(Origin Shield)

  场景 4:手动刷新(Purge)
  ═══════════════════════════════════
  你在 CDN 控制台主动刷新/清除了缓存
  → 下一个请求 → MISS → 回源
  → 这是预期行为,用于紧急更新内容

回源请求长什么样?

bash
# CDN 节点回源时发出的请求(和普通 HTTP 请求类似,但有特殊 Header)
GET /images/logo.png HTTP/1.1
Host: origin.example.com
X-Forwarded-For: 203.0.113.50        # 原始用户 IP
Via: 1.1 cdn-edge-sh01               # CDN 节点标识
If-None-Match: "abc123"              # 协商缓存(如有)
Accept-Encoding: gzip, br             # 压缩支持

回源的成本意识:

回源产生两种成本:

  ① 延迟成本
  ═══════════════════════════════════
  边缘节点在上海,源站在上海   → 回源延迟 ~10ms
  边缘节点在圣保罗,源站在上海 → 回源延迟 ~350ms
  → 中间层可以缩短:圣保罗边缘 → 美东中间层(~50ms)→ 上海源站

  ② 流量成本
  ═══════════════════════════════════
  大多数 CDN 厂商:回源流量另外计费!
  → 回源流量通常比 CDN 分发流量贵 2-5 倍
  → 命中率每提高 1%,回源流量就少 1%

4.2 回源策略:主备源站、权重轮询、故障转移

源站不只一个——配置多源站和故障转移策略,是生产环境的基本操作。

策略 1:主备源站
═══════════════════════════════════
  主源站:origin-1.example.com(所有回源请求发到这里)
  备源站:origin-2.example.com(主源站挂了才用)

  触发切换条件:
  → 主源站连续 3 次返回 5xx
  → 主源站连接超时(超过 30 秒)
  → 主源站健康检查失败

  适用:大多数网站——简单可靠


策略 2:权重轮询
═══════════════════════════════════
  源站 A:origin-a.example.com(权重 70%)
  源站 B:origin-b.example.com(权重 30%)

  → 70% 的回源请求发给 A,30% 发给 B
  → 可以用于灰度发布(新版源站权重 10% 试跑)

  适用:多机房部署、灰度场景


策略 3:就近回源
═══════════════════════════════════
  亚洲回源 → origin-asia.example.com
  欧洲回源 → origin-eu.example.com
  美洲回源 → origin-us.example.com

  → CDN 根据边缘节点所在区域选择最近的源站
  → 减少跨大洲回源延迟

  适用:全球部署了多个源站的大型应用

CDN 的健康检查机制:

CDN 怎么知道源站是否健康?

  ① 被动检测(默认)
  ═══════════════════════════════════
  正常回源时如果收到 5xx / 超时
  → 标记该源站为异常
  → 连续 N 次异常后切换到备源站
  → 恢复后自动切回

  ② 主动健康检查(推荐开启)
  ═══════════════════════════════════
  CDN 每隔 30 秒向源站发 HEAD 请求
  → 返回 200 → 健康
  → 返回 5xx 或超时 → 不健康
  → 不健康的源站直接从回源列表移除
  → 比被动检测更快发现故障(用户无感)

💡 生产环境必须配备源站。单一源站挂了,所有 CDN 节点的缓存过期后就无法更新——相当于全站逐渐失效。配一个备源站可能只需要一台廉价服务器做文件同步,成本极低但关键时刻能救命。

4.3 回源优化:合并回源、Range 回源、预热与刷新

回源不可避免,但可以让回源更高效——减少次数、减少流量、减少延迟。

合并回源(Request Coalescing / Collapsed Forwarding):

问题场景:
═══════════════════════════════════
  一个新文件(未缓存),1 秒内 100 个用户同时请求
  → 没有合并回源:CDN 向源站发 100 次相同请求 ❌
  → 源站压力 × 100

有合并回源:
═══════════════════════════════════
  第 1 个请求 → MISS → 发起回源
  第 2-100 个请求 → 发现已有回源请求在进行中
  → 排队等待,不重复回源
  → 第 1 个回源返回后 → 缓存 → 同时响应所有 100 个等待中的请求
  
  结果:100 个请求只触发 1 次回源 ✅

配置:大多数 CDN 默认开启,确认即可
  → Cloudflare:默认开启
  → 阿里云 CDN:需手动开启"回源合并"

Range 回源(大文件优化):

问题场景:
═══════════════════════════════════
  用户请求一个 2GB 的视频文件
  → CDN 没缓存 → 回源拉完整个 2GB?
  → 用户可能只看了前 30 秒就关掉了 → 浪费!

Range 回源:
═══════════════════════════════════
  CDN 不一次拉完,按需分段回源:
  → 用户请求 0-1MB → CDN 回源 Range: bytes=0-1048576
  → 用户继续播放 → CDN 继续回源下一段
  → 用户关掉了 → 停止回源(只拉了实际用到的部分)

  好处:
  ✅ 首字节到达更快(不等完整文件传完)
  ✅ 节省回源带宽(只拉用户实际需要的部分)
  ✅ 支持视频拖拽(Seek 到任意位置直接回源那段)

  前提:源站必须支持 Range 请求
  → Nginx、S3、OSS 默认支持
  → 自定义服务器需要实现 206 Partial Content

预热 vs 刷新——两个相反的操作:

操作含义效果使用场景
预热(Prefetch)主动把内容推到 CDN 节点第一个用户就能 HIT新上线、大促前
刷新(Purge)主动清除 CDN 上的缓存下一个请求会 MISS内容更新、紧急修复
预热和刷新的正确用法:

  发布新版前端:
  ═══════════════════════════════════
  1. 部署新文件到源站(新哈希名,不影响旧缓存)
  2. 预热:把新 JS/CSS 推到 CDN(curl 或 API)
  3. 更新 HTML(引用新的哈希文件名)
  4. 刷新:清除旧 HTML 缓存
  → 用户拿到新 HTML → 加载新 JS/CSS(已预热,秒加载)

  紧急修复线上 Bug:
  ═══════════════════════════════════
  1. 修复代码,部署到源站
  2. 刷新:清除受影响的 URL 缓存
  → CDN 下次请求回源拿到新内容
  → 注意:刷新有全球生效延迟(通常 1-5 分钟)

💡 "先预热再刷新"是版本发布的黄金顺序。先把新文件推到 CDN(预热),确保全球节点都有了,再刷新旧 HTML 让用户切到新版本——这样用户永远不会遇到"新 HTML 引用了新 JS,但 CDN 上还没有新 JS"的断档。

4.4 源站保护:防盗链、IP 白名单、鉴权 URL

你的源站 IP 不应该被直接访问——否则别人绕过 CDN 直连源站,你的缓存白做了,源站还可能被攻击。

防盗链(Referer 防护):

问题:别人在自己的网站上引用你的图片
═══════════════════════════════════
  <img src="https://static.你的域名.com/美女.jpg">
  → 他的用户看图片,你付 CDN 流量费
  → 叫"盗链"

解决:Referer 白名单
═══════════════════════════════════
  CDN 检查请求的 Referer Header:
  → Referer 在白名单(你自己的域名)→ 允许
  → Referer 不在或为空 → 返回 403 Forbidden

  配置示例(CDN 控制台):
  白名单:example.com, *.example.com
  是否允许空 Referer:否(防止直接访问)

回源 IP 白名单(源站防护):

问题:源站 IP 被泄露,攻击者绕过 CDN 直连
═══════════════════════════════════
  → CDN 被绕过,所有防护失效
  → 源站被 DDoS 打爆

解决:源站的防火墙只允许 CDN 的回源 IP
═══════════════════════════════════
  # Nginx 配置(只允许 CDN 回源 IP)
  allow 103.21.244.0/22;    # Cloudflare IP 段
  allow 103.22.200.0/22;
  allow 104.16.0.0/13;
  deny all;                  # 拒绝所有其他 IP

  各 CDN 厂商的回源 IP 列表:
  → Cloudflare: https://www.cloudflare.com/ips/
  → 阿里云 CDN: 控制台查看回源 IP 段
  → AWS CloudFront: aws ip-ranges.json

鉴权 URL(签名防盗链):

问题:Referer 防盗链可以伪造
═══════════════════════════════════
  → Referer 是 HTTP Header,很容易被修改
  → 高价值资源(付费视频/下载)需要更强的保护

解决:URL 签名——带有限时 Token 的 URL
═══════════════════════════════════
  原始 URL:/video/premium.mp4
  签名 URL:/video/premium.mp4?sign=abc123&t=1705315200

  签名生成规则(服务端):
  sign = MD5(secret_key + 文件路径 + 过期时间戳)
  t = 过期时间戳(Unix timestamp)

  CDN 验证逻辑:
  ① 检查 t 是否过期 → 过期 → 403
  ② 用相同规则计算签名 → 不匹配 → 403
  ③ 签名正确且未过期 → 允许访问

  优势:
  ✅ 无法伪造(不知道 secret_key)
  ✅ 有时间限制(链接过期失效)
  ✅ 可以绑定用户 IP(防止分享链接)

💡 安全防护要分层:Referer 防盗链挡住 90% 的普通盗链(成本低、简单);回源 IP 白名单防止源站被绕过(必须做);鉴权 URL 保护高价值资源(付费内容必须做)。三者不是互斥的,应该叠加使用。

第 4 章核心知识回顾:

概念一句话解释
回源四场景首次请求、缓存过期、LRU 淘汰、手动刷新
主备源站主源异常自动切备源,生产环境必须配
合并回源多个 MISS 只发一次回源请求,防止"回源风暴"
Range 回源大文件分段拉取,节省带宽、降低首字节延迟
先预热再刷新版本发布黄金顺序,避免 CDN 断档
源站保护Referer 防盗链 + IP 白名单 + 签名 URL 三层防护

5. HTTPS 与安全加速

2024 年不上 HTTPS 基本等于"不存在"——Chrome 标记 HTTP 为"不安全"、搜索引擎降权、HTTP/2 和 HTTP/3 强制要求 HTTPS。CDN 上部署 HTTPS 不只是"上个证书"——TLS 握手本身可能增加 1-2 个 RTT,优化不好反而变慢。

5.1 CDN 上部署 HTTPS:证书管理与 SNI

CDN 的 HTTPS 架构——两段加密:

用户 ←──── HTTPS ────→ CDN 边缘节点 ←──── HTTPS ────→ 源站
     (用户到边缘的加密)              (边缘到源站的加密)

两段可以独立配置:
  → 用户到 CDN:必须 HTTPS(用户体验 + 安全)
  → CDN 到源站:可选 HTTPS 或 HTTP(看安全要求)

CDN 回源协议选择:

回源协议安全性性能适用场景
HTTPS 回源⭐⭐⭐⭐⭐稍慢(TLS 握手)敏感数据(登录/支付)
HTTP 回源⭐⭐更快纯静态资源(图片/CSS)
协议跟随跟随用户请求视情况混合场景

证书部署方式:

方式 1:CDN 厂商免费证书(推荐入门)
═══════════════════════════════════
  → Cloudflare:自动签发,点一下就开启 HTTPS
  → 阿里云 CDN:免费 DV 证书,一键申请
  → 优点:零成本、自动续期
  → 缺点:只支持单域名

方式 2:上传自有证书
═══════════════════════════════════
  → 上传证书文件(.pem)+ 私钥(.key)到 CDN 控制台
  → 支持通配符证书(*.example.com)
  → 需要自己管理续期
  → 适合:多子域名、企业级证书

方式 3:Let's Encrypt 自动化
═══════════════════════════════════
  → 用 certbot 自动签发 + 自动续期
  → 通过 DNS-01 验证(配合 CDN 的 DNS API)
  → 适合:自动化运维团队

SNI(Server Name Indication)——一个 IP 多个证书:

问题:CDN 边缘节点一个 IP 要服务数百万个域名
═══════════════════════════════════
  → 传统 HTTPS:一个 IP 只能绑一个证书
  → CDN 有几千个域名,不可能给每个域名分 IP

解决:SNI 扩展
═══════════════════════════════════
  TLS 握手时,客户端在 ClientHello 中告诉服务器:
  "我要访问的是 static.example.com"
  → CDN 根据域名找到对应的证书
  → 一个 IP 可以服务无数个域名

  兼容性:所有现代浏览器都支持
  唯一问题:极老的客户端(IE6/WinXP)不支持 SNI
  → 2024 年可以无视这个问题

5.2 TLS 优化三板斧:OCSP Stapling / TLS 1.3 / Session Resumption

TLS 握手是 HTTPS 的性能瓶颈——每次新连接需要 1-2 个额外 RTT。以下三项优化能把 TLS 开销降到最低:

优化 1:TLS 1.3(最重要)
═══════════════════════════════════
  TLS 1.2 握手:2 个 RTT
  TLS 1.3 握手:1 个 RTT
  TLS 1.3 0-RTT:0 个 RTT(重复连接)

  → 每次连接省 1 个 RTT
  → 跨大洲连接(RTT 200ms)省 200ms——用户能感知的差距
  
  配置:CDN 控制台开启 TLS 1.3(大多数默认已开启)
  兼容性:所有现代浏览器均支持


优化 2:OCSP Stapling(消除证书验证延迟)
═══════════════════════════════════
  问题:浏览器需要验证证书是否被吊销
  → 向 CA 的 OCSP 服务器发请求
  → OCSP 服务器可能在国外 → 额外 100-500ms 延迟
  → 有时 OCSP 服务器慢或挂了 → 更离谱的延迟

  解决:OCSP Stapling
  → CDN 节点定期获取 OCSP 响应并缓存
  → TLS 握手时直接把 OCSP 响应"钉"在证书上发给浏览器
  → 浏览器不需要再单独查询 OCSP → 省一次外部请求

  Nginx 配置:
  ssl_stapling on;
  ssl_stapling_verify on;

  CDN 配置:大多数厂商默认开启


优化 3:Session Resumption(跳过重复握手)
═══════════════════════════════════
  问题:用户打开多个页面,每个页面都要 TLS 握手?
  
  解决 A:Session ID
  → 服务器缓存 Session 状态
  → 客户端重连时携带 Session ID → 跳过完整握手
  → 问题:CDN 有数百个节点,Session 不共享

  解决 B:Session Ticket(推荐)
  → 服务器把 Session 状态加密后发给客户端保存
  → 客户端重连时携带 Ticket → 任何节点都能解密恢复
  → 不需要节点间共享状态 → 完美适配 CDN 架构

  效果:重复连接 TLS 握手从 1 RTT → 0 RTT

TLS 优化效果对比:

配置首次连接延迟重复连接延迟推荐
TLS 1.2 无优化+2 RTT+1 RTT
TLS 1.3+1 RTT+1 RTT
TLS 1.3 + Session Ticket+1 RTT+0 RTT✅✅
TLS 1.3 + 0-RTT+1 RTT+0 RTT⚠️ 有安全风险

💡 TLS 1.3 + OCSP Stapling + Session Ticket 是标配。大多数 CDN 厂商默认开启,你需要做的只是确认。在 CDN 控制台检查这三项:① TLS 最低版本设为 1.2(兼容)或 1.3(激进)② OCSP Stapling 开启 ③ Session Ticket 开启。

5.3 安全防护:WAF、DDoS 防护、Bot 管理

CDN 不只是"加速器"——因为所有流量都经过 CDN,它是天然的安全屏障。现代 CDN 厂商都在边缘节点集成了安全能力。

CDN 的三层安全防护:

  Layer 1: DDoS 防护(网络层/传输层)
  ═══════════════════════════════════
  攻击类型:SYN Flood / UDP Flood / DNS 放大攻击
  防护原理:
    → Anycast 把攻击流量分散到全球节点
    → 每个节点过滤异常流量
    → 单节点承受 1Tbps 攻击,分散到 300 个节点 = 每个只需处理 3.3Gbps
  
  效果:Cloudflare Free 套餐就包含无限 DDoS 防护
  配置:无需配置,默认生效


  Layer 2: WAF(应用层防火墙)
  ═══════════════════════════════════
  攻击类型:SQL 注入 / XSS / CSRF / 文件包含
  防护原理:
    → 边缘节点检查每个 HTTP 请求的内容
    → 匹配 OWASP Top 10 攻击规则
    → 命中规则 → 拦截或记录
  
  典型规则:
    → 请求中包含 ' OR 1=1 -- → 拦截(SQL 注入)
    → 请求中包含 <script> → 拦截(XSS)
    → 非法文件上传 → 拦截
  
  配置:CDN 控制台开启 WAF,选择托管规则集
  费用:Cloudflare Pro($20/月)起、阿里云 WAF 另购


  Layer 3: Bot 管理(机器人防护)
  ═══════════════════════════════════
  问题:不是所有 Bot 都是坏的
    → 好 Bot:Googlebot(搜索索引)、监控服务
    → 坏 Bot:爬虫、撞库、囤货抢购、API 滥用
  
  防护手段:
    → JS Challenge:要求执行 JavaScript(纯 Bot 做不到)
    → CAPTCHA Challenge:人机验证
    → 行为分析:鼠标轨迹、点击频率、浏览模式
    → IP 信誉库:已知恶意 IP 直接拦截
  
  配置:设定安全级别(低/中/高/Under Attack)

各 CDN 厂商的安全能力对比:

能力Cloudflare FreeCloudflare Pro阿里云 CDNAWS CloudFront
DDoS 防护✅ 无限✅ 无限✅ 基础✅ AWS Shield
WAF基础规则✅ OWASP 全集需购 WAF需购 AWS WAF
Bot 管理JS Challenge✅ 高级基础需额外配置
速率限制基础✅ 自定义✅ 自定义✅ 自定义
月费起步免费$20~¥100按用量

💡 CDN 的安全价值常被低估。很多公司单独购买 DDoS 防护和 WAF 服务,每月花费数万元——而 Cloudflare Pro 套餐 $20/月就包含了全部。如果你已经在用 CDN,先检查它自带的安全能力,很可能不需要额外购买安全产品。

第 5 章核心知识回顾:

概念一句话解释
两段加密用户→CDN 和 CDN→源站 的 HTTPS 可独立配置
SNI一个 IP 服务多个域名的 HTTPS,现代标准
TLS 1.3握手从 2 RTT 降到 1 RTT,必须开启
OCSP Stapling消除证书验证的额外网络请求延迟
Session Ticket重复连接跳过 TLS 握手,适配 CDN 多节点架构
CDN 安全DDoS + WAF + Bot 管理三层防护,用 CDN 就能获得

6. 全站加速(动态加速)

前面五章讲的都是"静态加速"——把图片、CSS、JS 缓存到边缘节点。但 API 接口返回的数据每次都不同、不能缓存——怎么加速?这就是"动态加速"(DCDN)。

6.1 静态加速 vs 动态加速——区别在哪

静态加速(CDN 传统能力)
═══════════════════════════════════
  加速原理:缓存内容到边缘节点
  适用内容:图片、CSS、JS、视频、字体
  核心指标:缓存命中率(越高越好)
  延迟来源:边缘节点到用户的距离
  
  用户 → CDN 边缘(有缓存,直接返回)
  延迟:1-10ms ✅

动态加速(DCDN / 全站加速)
═══════════════════════════════════
  加速原理:优化传输路径(不缓存内容)
  适用内容:API 接口、登录、搜索、个性化页面
  核心指标:回源延迟(越低越好)
  延迟来源:源站处理时间 + 网络传输时间

  用户 → CDN 边缘 → 优化路径 → 源站 → 返回
  延迟:比直连源站快 30-60%

为什么动态加速比直连快?(明明都要回源)

直连源站:
═══════════════════════════════════
  圣保罗用户 ─── 公网 ──→ 上海源站
  → 公网路由不可控,可能绕道、拥堵
  → 跨运营商、跨国交换节点多
  → RTT: 350ms(不稳定,有时 500ms+)

动态加速:
═══════════════════════════════════
  圣保罗用户 → 圣保罗 CDN 节点
           → CDN 骨干网(专线/优化路由)
           → 上海 CDN 节点 → 上海源站
  → 用 CDN 厂商的骨干网替代公网
  → 路由优化、TCP 优化、连接复用
  → RTT: 200ms(更稳定)

6.2 动态路径优化:智能路由、TCP 优化、连接复用

动态加速的三大核心技术:

技术 1:智能路由(最重要)
═══════════════════════════════════
  CDN 厂商在全球节点间建立了"专线网络"
  → 实时探测各条路径的延迟和丢包率
  → 自动选择当前最快的路径转发请求
  
  类比:公网是普通公路(红灯、堵车、绕路)
       CDN 骨干网是高速公路(直达、不堵)

  效果:跨大洲延迟降低 30-50%


技术 2:TCP 优化
═══════════════════════════════════
  问题:TCP 在长距离高延迟链路上性能差
  → 慢启动需要好几个 RTT 才能跑满带宽
  → 丢包后窗口减半,恢复慢

  CDN 的 TCP 优化:
  → 边缘节点代理 TCP 连接(拆成两段短连接)
  → 用户 ↔ 边缘:低延迟短连接,快速握手
  → 边缘 ↔ 源站:长连接复用,已经过慢启动阶段
  → 定制拥塞控制算法(BBR 等)
  
  效果:小文件传输速度提升 2-3 倍


技术 3:连接复用(Keep-Alive / 长连接池)
═══════════════════════════════════
  问题:每个用户请求都新建 TCP + TLS 连接?
  → 握手成本太高(3-5 个 RTT)

  CDN 连接复用:
  → 边缘节点维护到源站的长连接池
  → 多个用户请求复用同一条连接
  → 省掉了 TCP + TLS 握手

  效果:消除源站方向的握手延迟

6.3 全站加速实战:API 接口 + 静态资源混合加速配置

实际项目中,你的网站既有静态资源又有 API——需要分开配置。

方案 1:双域名分流(推荐)
═══════════════════════════════════
  static.example.com → 普通 CDN(静态加速)
    → 配置缓存规则、长 TTL
    → 命中率目标 95%+
  
  api.example.com → DCDN(动态加速)
    → 不缓存,走智能路由
    → 优化传输路径

  好处:
  ✅ 缓存策略互不干扰
  ✅ 静态域名用便宜的 CDN 计费
  ✅ 动态域名用专业的 DCDN 优化


方案 2:同域名路径分流
═══════════════════════════════════
  example.com/static/* → 走缓存(静态加速)
  example.com/api/*    → 不缓存(动态加速)

  CDN 配置:
  → /static/* 路径:缓存 30 天
  → /api/* 路径:回源,开启动态加速
  → / 路径:缓存 5 分钟(HTML)

  好处:不需要改代码中的域名引用
  缺点:Cookie 可能污染静态资源缓存

各厂商全站加速产品:

厂商产品名特点
CloudflareArgo Smart Routing通过 Cloudflare 骨干网转发,延迟降低 30%
阿里云全站加速 DCDN智能路由 + TCP 优化 + WebSocket 支持
AWSGlobal AcceleratorAnycast + AWS 骨干网,适合 API 加速
腾讯云ECDN动静混合加速,自动识别内容类型

💡 90% 的网站只需要静态 CDN。动态加速(DCDN)的费用通常是静态 CDN 的 3-5 倍,只有当你的用户分布全球且 API 延迟是核心痛点时才值得上。先把静态资源的缓存命中率做到 95%+,再考虑 API 加速。

第 6 章核心知识回顾:

概念一句话解释
静态加速缓存内容到边缘节点,命中率是核心
动态加速不缓存内容,优化传输路径(骨干网替代公网)
智能路由实时探测选择最快路径,跨大洲延迟降低 30-50%
TCP 优化边缘代理连接 + 定制拥塞控制,小文件速度翻倍
双域名分流static 走缓存 CDN,api 走动态 DCDN,互不干扰

7. 边缘计算与 Edge Functions

CDN 节点过去只做一件事:缓存文件、返回文件。但现在,你可以在边缘节点上运行代码——不需要回源站,直接在离用户最近的地方处理请求。这就是"边缘计算"。

7.1 什么是边缘计算:从"缓存代理"到"计算节点"

传统 CDN 节点的能力:
═══════════════════════════════════
  收到请求 → 有缓存就返回,没有就回源
  → 只做"搬运",不做"计算"

边缘计算的能力:
═══════════════════════════════════
  收到请求 → 运行你写的代码 → 返回结果
  → 可以修改请求、改写响应、做逻辑判断
  → 不需要回源站
  → 响应时间 = 边缘节点到用户的延迟(1-10ms)

能做什么?
  → URL 重写和重定向
  → A/B 测试(在边缘分流,不需要后端改代码)
  → 地理定向(根据用户国家返回不同内容)
  → 请求鉴权(JWT 验证在边缘完成)
  → HTML 注入(在边缘往 HTML 里插入脚本/样式)
  → API 聚合(在边缘合并多个后端 API 的结果)

7.2 主流方案对比:Cloudflare Workers / Vercel Edge / AWS Lambda@Edge

Cloudflare Workers(推荐入门)
═══════════════════════════════════
  运行时:V8 Isolates(和 Chrome 相同的 JS 引擎)
  语言:JavaScript / TypeScript / Wasm
  冷启动:0ms(V8 Isolate 没有冷启动问题)
  部署范围:300+ 全球节点
  免费额度:10 万次/天
  配套服务:KV(键值存储)、D1(SQLite)、R2(对象存储)

  优势:
  ✅ 冷启动为零,响应极快
  ✅ 免费额度够个人项目用
  ✅ 配套存储服务丰富
  ✅ 部署简单(wrangler deploy 一条命令)


Vercel Edge Functions
═══════════════════════════════════
  运行时:Edge Runtime(基于 V8)
  语言:JavaScript / TypeScript
  冷启动:极低
  部署范围:与 Vercel 网络一致
  免费额度:包含在 Hobby 套餐中

  优势:
  ✅ 与 Next.js 深度集成(middleware.ts 自动部署到边缘)
  ✅ 对前端开发者最友好
  缺点:绑定 Vercel 平台


AWS Lambda@Edge / CloudFront Functions
═══════════════════════════════════
  运行时:Node.js(Lambda@Edge)/ JavaScript(CF Functions)
  冷启动:Lambda@Edge 有冷启动(100-500ms)
  部署范围:CloudFront 全球节点

  优势:
  ✅ AWS 生态集成
  ✅ CloudFront Functions 轻量级(无冷启动)
  缺点:Lambda@Edge 冷启动影响体验

三者对比:

维度Cloudflare WorkersVercel EdgeLambda@Edge
冷启动0ms~0ms100-500ms
免费额度10 万次/天含 Hobby100 万次/月
配套存储KV / D1 / R2Vercel KVDynamoDB
部署便捷⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
适合场景通用边缘计算Next.js 项目AWS 重度用户

7.3 边缘计算实战:A/B 测试、地理定向、请求改写

三个最常见的边缘计算用例(Cloudflare Workers 示例):

实战 1:A/B 测试(在边缘分流,零后端改动)

javascript
// 边缘 A/B 测试:50% 用户看新版首页,50% 看旧版
export default {
  async fetch(request) {
    const url = new URL(request.url);
    
    // 用 Cookie 保持用户分组一致
    const cookie = request.headers.get('Cookie') || '';
    let variant = cookie.includes('ab=new') ? 'new' : 
                  cookie.includes('ab=old') ? 'old' : null;
    
    // 新用户随机分组
    if (!variant) {
      variant = Math.random() < 0.5 ? 'new' : 'old';
    }
    
    // 根据分组修改请求路径
    if (variant === 'new' && url.pathname === '/') {
      url.pathname = '/new-homepage';
    }
    
    const response = await fetch(url, request);
    const newResponse = new Response(response.body, response);
    newResponse.headers.set('Set-Cookie', `ab=${variant}; Path=/; Max-Age=86400`);
    return newResponse;
  }
};

实战 2:地理定向(根据国家返回不同内容)

javascript
// 根据用户国家重定向到对应站点
export default {
  async fetch(request) {
    const country = request.cf?.country || 'US';
    
    const countryMap = {
      'CN': 'https://cn.example.com',
      'JP': 'https://jp.example.com',
      'KR': 'https://kr.example.com',
    };
    
    if (countryMap[country]) {
      return Response.redirect(countryMap[country] + new URL(request.url).pathname, 302);
    }
    
    return fetch(request);  // 默认回源
  }
};

实战 3:请求改写(在边缘添加 Header / 修改响应)

javascript
// 添加安全 Header + 注入性能监控脚本
export default {
  async fetch(request) {
    const response = await fetch(request);
    const newResponse = new Response(response.body, response);
    
    // 添加安全 Header
    newResponse.headers.set('X-Content-Type-Options', 'nosniff');
    newResponse.headers.set('X-Frame-Options', 'DENY');
    newResponse.headers.set('Strict-Transport-Security', 'max-age=31536000');
    
    return newResponse;
  }
};

💡 边缘计算的核心价值是"在用户身边做决策"。A/B 测试、地理定向、鉴权这些操作,传统方案需要请求到达源站才能处理——跨大洲延迟 200ms。在边缘做,延迟 < 10ms。而且完全不增加源站负载。

第 7 章核心知识回顾:

概念一句话解释
边缘计算在 CDN 节点运行代码,不回源站直接处理请求
Cloudflare WorkersV8 Isolates,0 冷启动,最推荐的边缘计算平台
A/B 测试在边缘按规则分流用户,零后端改动
地理定向根据 request.cf.country 返回不同内容
适用场景请求改写、鉴权、分流、Header 注入——轻逻辑

8. CDN 配置实战

8.1 Cloudflare 配置实战:免费 CDN + DNS + SSL

8.2 阿里云 CDN 配置实战:域名接入、缓存规则、HTTPS

8.3 多 CDN 策略:主备切换、流量分发、一致性保障


9. 监控、调试与成本控制

9.1 CDN 核心指标监控:命中率、回源率、延迟、带宽

9.2 调试技巧:curl 看 CDN Header、X-Cache 状态、Trace 路由

9.3 成本控制:带宽计费 vs 流量计费、闲时预热、图片压缩


10. 最佳实践与常见坑

10.1 静态资源部署最佳实践:哈希命名、长缓存、版本管理

10.2 常见问题排查清单:缓存不生效、域名解析慢、证书错误

10.3 CDN 与现代前端框架(Next.js / Vite)的集成

坚持是一种品格