9.2 回源策略与回源率

一句话

回源策略决定 “拿不到时向谁要、怎么要、要不到怎么办”,回源率是它的成绩单——回源率从 30% 降到 8%,源站带宽与尾延迟一起下一个台阶;而 “回源风暴” 几乎总是配置问题,不是流量问题。

回源配置:七项,每项都有默认坑

配置 常见取值 配错的后果
回源 HOST 与加速域名一致 / 源站真实域名 写成 IP → 源站证书不匹配(SNI 校验失败),只能降级 HTTP
回源协议 HTTP / HTTPS / 跟随客户端 跟随客户端时会混用协议,源站侧缓存与重定向混乱
回源端口 80 / 443 / 自定义 自定义端口忘记在安全组放行 → 全量 502
连接超时 3–5 秒 设 60 秒 → 源站慢时连接堆积,边缘线程被占满
读取超时 10–30 秒 与大文件下载冲突;下载类要单独放宽
重试次数 1–2 次(只对幂等方法) 对 POST 重试 → 重复下单
跟随重定向 开 / 关 关:源站 302 直接透传给用户;开:边缘替你跳,但可能跳出加速域

回源模式:四种,选错会在故障时放大

模式 怎么做 适合 风险
单源 全部回一个源站 小站、验证期 源站挂 = 全站挂
主备 主源失败切备源 迁移期、灾备 备源数据滞后,切过去可能读到旧内容
多源加权 按权重/地域分回多个源 多机房、异地部署 缓存不一致:同一 URL 在两个源内容不同
源站组 + 健康检查 自动剔除不健康源 生产推荐 健康检查本身会给源站带来额外 QPS

一条判据:多源的前提是 “内容一致或按地域一致”。如果没有一致性保障,多源只会把 “缓存不一致” 变成随机故障。

回源率:定义、目标与四个降法

回源率 = 回源请求数 / 边缘总请求数
内容类型 合理回源率 说明
静态资源(图片/JS/CSS) 5%–15% 低于 5% 往往意味着 TTL 太长或内容不更新
下载/点播分片 10%–30% 长尾文件多,命中率天然偏低
动态接口 接近 100% 不可缓存的不该追求低回源率

四个降法按性价比排序:

手段 效果 代价
延长 TTL(在可接受的新鲜度内) 直接降低回源 内容更新变慢(靠刷新/版本化补偿,见 9.4 预热、刷新与失效)
修正缓存键(去掉随机参数与无关 Cookie) 命中率可能翻倍 需要梳理业务参数(见 9.3 缓存键设计)
请求合并(single-flight) 把 “N 个并发 MISS” 压成 1 次回源 实现成本;需要锁与超时
预热主要对象 发布瞬间不打源站 只对可枚举的对象有效

回源风暴:一个 MISS 引发的雪崩

典型链条:刷新/过期 → 大量请求同时 MISS → 每个边缘节点各自回源 → 源站被打满 → 超时 → 重试放大 → 全站不可用。

防护 做法
请求合并 同一 URL 在边缘只允许一个回源在飞,其余等待共享结果
回源限速 单节点对单源站的并发/速率上限(超出排队或直接返回旧副本)
stale-if-error 回源失败时返回过期副本(短期脏数据好过 5xx)
源站侧过载保护 限流 + 队列 + 快速失败,而不是排队到超时
分散过期 给 TTL 加随机抖动(±10%),避免同一秒集体过期

指标:四个数就能判断回源是否健康

指标 健康信号 异常含义
回源率 稳定在目标区间 突升 → 键/TTL/刷新出问题
回源 QPS 与命中流量成比例 远高于预期 → 合并失效或键碎片化
回源 5xx / 超时 < 0.1% 上升 → 源站过载或回源配置错
回源 P95 延迟 与源站自身 P95 接近 明显更高 → 链路绕路或回源 HOST 错配

反模式

反模式 后果
回源超时设 60 秒 源站抖动时边缘连接被占满,故障扩散到全站
对 POST 开启回源重试 重复提交/重复扣款
回源 HOST 填 IP 证书与 SNI 不匹配,只能退回 HTTP
多源但没有一致性保障 同一 URL 在不同节点返回不同内容
把 “回源率低” 当唯一目标 TTL 过长导致内容陈旧,用户看到旧版本
刷新后不打预热 刷新瞬间全量 MISS,源站被自己的发布打挂
没有回源限速 一个热点对象就能打满源站出口

三条铁律

🔑 回源是 “最后一道容量闸”:源站的容量要按 “最坏情况下的回源率” 设计,不是按平均。

🔑 合并 + 限速 + stale-if-error,三者合起来才防得住回源风暴。

🔑 多源的前提是内容一致;否则你只是把故障从 “源站挂” 换成 “随机脏数据”。

自检

Q1 一次发布后源站 CPU 打满,CDN 回源率从 8% 飙到 60%。最可能发生了什么?

▸ 答案:刷新/新版本导致全量 MISS,且没有预热或合并。新文件名(或刷新后的 URL)在边缘全部未命中,大量请求同时回源;若回源还没有请求合并,一个 URL 的 N 个并发会变成 N 次回源。修法:发布前预热、开请求合并、回源限速,并给 TTL 加抖动避免集体过期。

Q2 回源超时应该设多少?为什么不是越大越好?

▸ 答案:连接超时 3–5 秒、读取超时 10–30 秒(下载类单独放宽)。设大(如 60 秒)的问题是边缘资源被慢请求占住:源站一抖动,所有边缘连接都卡在等待上,正常请求也排队,故障从 “源站慢” 放大成 “边缘不可用”。超时是保护边缘的手段,不是给源站留面子。

Q3 为什么 “同一个 URL 配置了两个源站” 会出随机问题?

▸ 答案:因为两个源站的内容可能不同步(发布只推了一台、缓存没清、数据库主从延迟)。用户这次命中 A、下次命中 B,看到的内容跳变;更糟的是边缘缓存会把两个版本分别缓存,问题持续存在。多源必须先保证 “内容一致或按规则一致”,否则应先修一致性再谈多源。

Q4 什么情况下回源率高是正常的?

▸ 答案:动态接口。登录、下单、查询个人订单这类内容不可缓存,回源率接近 100% 是设计如此。此时要优化的是 “回源链路” 而不是 “命中率”——用长连接、协议优化、就近回源(见 9.5 动态加速)。把动态请求也缓存,是另一类事故(用户看到别人的数据)。

Q5 stale-if-error 会不会让用户长期看到旧内容?

▸ 答案:不会,只要配好边界:它只在 回源失败 时生效,且有 stale-while-revalidate / stale-if-error 的最大时长(如 60 秒–5 分钟)。代价是 “故障期间可能看到几分钟前的数据”,收益是 “源站抖动时用户仍能打开页面”。对价格、库存这类强一致内容,应关闭或把窗口压到极短,并在应用层做版本校验。

跨篇相关:命中率与回源放大的原理见 9.1 边缘缓存原理;键设计决定回源率的上限见 9.3 缓存键设计;刷新与预热的配合见 9.4 预热、刷新与失效;不可缓存内容的加速见 9.5 动态加速;CDN 的整体组成见 9.0 CDN 全景:它到底是什么;回源流量的计费见 5.6 云成本结构。