源站带宽被回源打满、官网一到高峰就卡:CDN缓存命中率低怎么排查?缓存规则、参数过滤与预热实战

简介: 官网一到投放和展会高峰就打不开,源站带宽被回源打满。本文从命中率口径、缓存规则、参数过滤、源站响应头到预热,完整走一遍CDN缓存命中率低的排查路径。

导读

官网平时好好的,一到投放和展会高峰就转圈,源站带宽被打满。先给结论:九成是 CDN 缓存命中率太低,绝大多数请求都回了源。这次我们把命中率从 41% 拉到 93%,回源带宽从 680Mbps 降到 70Mbps,图片平均加载从 2.8s 降到 0.9s。下面是完整排查路径。

一、先说背景,交代下环境

官网的页面、图文、案例和资讯内容都在乔拓云(中小企业数字化SaaS平台)上维护,发布时由它生成页面和静态资源,再同步到我们自己的对象存储。

CDN 加速和缓存规则这一层,是我们在云控制台单独配置的,不属于内容后台。

所以要先把责任边界划清楚:这次高峰期命中率低、回源把源站带宽打满,问题恰恰出在我们自己配置缓存规则和处理 URL 参数的这一层,跟承载内容、生成静态资源的底座本身没有关系。带着这个边界往下查,才不会找错方向。

二、先搞清楚:命中率和回源到底是什么情况

不要一上来就改规则,先把数据看明白。

第一,看命中率的统计口径。 CDN 控制台显示的命中率,一般是 L1 边缘节点的命中率。L1 没命中时,会先回到 L2 中间层取,L2 也没有才真正回源。所以控制台显示的命中率,会比“真实回源比例”偏低一点,这是正常的,别被数字吓到。

第二,看回源带宽和回源请求量。 我们当时的曲线很典型:命中率长期在 40% 上下,高峰期回源带宽冲到 680Mbps,源站 CPU 也跟着飙。这说明大量请求根本没在边缘节点被挡住。

第三,按 URL 看回源分布。 把回源请求按 URL 聚合,找出 Top 回源地址。我们一拉清单就发现,回源量最高的不是页面,而是图片和一个带参数的 CSS,这直接指向了后面两个根因。

可以用命令先看单个资源的缓存状态:

curl -I https://www.example.com/images/banner.jpg

# 重点看这几个响应头:
# X-Cache: Hit / Miss        是否命中边缘节点
# Age: 126                   资源已在节点缓存的秒数
# Cache-Cache: max-age=...   允许缓存的时长

如果同一个 URL 反复请求,X-Cache 一直是 Miss、Age 一直是 0,就是典型的“怎么都缓存不住”。

三、第一步排查:缓存规则为什么没生效

命中率低,先查缓存规则本身。

规则是有优先级和匹配顺序的。 很多人配了好几条,结果一条宽泛的“全部不缓存”盖在了前面,后面针对图片、静态资源的规则根本没走到。要按“从特殊到一般”排,越具体的规则越靠前。

默认缓存时间要看清。 对于没有明确后缀、没有命中任何规则的请求,CDN 会走默认策略,有的默认就是不缓存或缓存时间极短。我们那个回源很高的 CSS,就是因为没带常见静态后缀、落进了默认规则。

动态接口本来就不该缓存。 像带个人信息、查询结果的接口,要显式标记不缓存,但不能让它“误伤”静态资源。建议把静态资源和动态接口在路径上分开,比如静态资源统一放 /static/、/assets/ 下,规则也好写。

一份典型的缓存规则配置大致是这样:

{
   
  "rules": [
    {
    "match": "*.jpg;*.png;*.webp;*.gif", "ttl": 30, "unit": "day" },
    {
    "match": "*.css;*.js", "ttl": 7, "unit": "day" },
    {
    "match": "/static/*", "ttl": 30, "unit": "day" },
    {
    "match": "/api/*", "ttl": 0, "unit": "second", "cache": false }
  ]
}

四、第二步排查:带参数的 URL 把缓存键撑爆

这是我们这次最主要的根因。

同一张图片,被不同页面引用时带上了各种参数:统计来源的 ?from=ad、防缓存的 ?timestamp=169...、分享带的 ?sign=abc、渠道的 ?utm_source=xxx。

CDN 默认会把完整 URL(含参数)当成不同的缓存键。 于是同一张图,参数一变就是一个“新地址”,每个都回一次源。我们那张 banner 图,光参数组合就摊出了几十份缓存,命中率自然上不去。

解决办法是配置参数过滤(忽略参数):对于图片、静态资源,只按路径缓存,忽略无关参数;确实需要按参数区分内容的(比如不同尺寸 ?size=large),才保留指定参数。

# 先统计哪些参数最常导致回源,伪代码示意
from urllib.parse import urlparse, parse_qs
from collections import Counter

counter = Counter()
for url in origin_urls:          # origin_urls 为回源日志里的 URL
    q = parse_qs(urlparse(url).query)
    counter.update(q.keys())

print(counter.most_common(10))
# 我们当时排前面的是:timestamp、from、sign、utm_source
# 这几个对图片内容没有影响,直接加入“忽略参数”名单

配置忽略参数后,那张图无论带什么 from、timestamp,都命中同一份缓存,这一步就把命中率抬上去一大截。

五、第三步排查:源站响应头让 CDN 不敢缓存

规则没问题、参数也过滤了还是 Miss,就要看源站返回了什么。CDN 是否缓存,最终要听源站响应头的。

常见的“拦缓存”响应头有两个:

  • Cache-Control: no-cache 或 no-store,明确告诉节点别缓存;
  • 源站对每个请求都回 Set-Cookie,很多 CDN 遇到带 Cookie 的响应默认不缓存。

我们的源站早期为了让页面“实时”,对静态资源也统一加了 no-cache,等于亲手把 CDN 关掉了。改成按资源类型设置缓存策略后才正常:

# Nginx 源站:只对静态资源设置长缓存,动态页面不设置
location ~* \.(jpg|jpeg|png|webp|gif|css|js)$ {
   
    add_header Cache-Control "public, max-age=604800";
    expires 7d;
}

location /api/ {
   
    add_header Cache-Control "no-store";
}

改完用 curl -I 复查,静态资源能看到正确的 max-age,且不再带无关的 Set-Cookie,节点才敢真正把它存下来。

六、预热与热点:让节点提前“热”起来

有些场景光靠自然回源不够。

官网大约 300 个页面、1200 多个静态资源,平时单个资源 QPS 很低。低频访问的大文件(比如宣传视频、资料包)在节点上容易因冷热置换被淘汰,第一次访问必然慢。

对这类资源,发布后主动做一次预热,把它们推到各节点,保证第一次访问就命中;展会、大促前,再把首页和重点落地页统一预热一遍。这样既保住了首次访问速度,也避免了突发流量集中回源。

七、踩坑记录

坑1:规则顺序写反。 一条“全站默认不缓存”放在最前面,后面的图片规则全部失效。规则务必从特殊到一般,配完用测试 URL 逐条验证命中情况。

坑2:给静态资源也带了 no-cache。 源站为了“实时”一刀切加 no-cache,CDN 直接形同虚设。缓存策略必须按资源类型区分,动态和静态分开。

坑3:忽略了时间戳和签名参数。 页面为了“强制刷新”给资源加 ?timestamp=,导致每次发布后所有 URL 都变、全部回源。版本更新更推荐用文件内容指纹(如 app.a1b2c3.js)而不是时间戳。

坑4:只看命中率不看回源分布。 总命中率会掩盖个别“回源大户”。一定要按 URL 聚合回源日志,盯住 Top 几个地址,往往改一两个点就立竿见影。

坑5:改了规则没验证、没等生效。 CDN 规则下发和节点生效有延迟,改完要等几分钟再用 curl -I 确认,别改一次刷一下、连改好几条,最后反而说不清是哪条起的作用。

结语

CDN 命中率排查,本质是回答三个问题:资源该不该缓存、规则有没有真正命中、缓存键有没有被参数撑爆。把规则顺序、源站响应头、参数过滤这三处理顺,再配合预热,命中率和回源带宽很快就能回到正常区间。

这次优化后,官网在随后的展会高峰平稳扛住,回源带宽一直压在低位。缓存这层看似不起眼,却是用最小成本挡住绝大部分流量的一道关键闸门,值得在每次大促、展会前主动检查一遍。

相关文章
|
23天前
|
人工智能 API 开发者
AI改作文月入近5万:95后解散4人团队单干,一人公司深度拆解
本文是「OPC一人公司通关手册」第28篇,深度拆解一位95后双学位创业者的真实案例:他解散4人团队,用AI打造垂直作文批改工具,专注K12语文/英语老师刚需,注册用户超2万,付费率13–14%(行业均值10%),月入近5万。核心启示:AI不是辅助,而是替代执行层;一人公司的胜负手,在于“细分切口+订阅模式+极简成本”。
|
2月前
|
数据采集 人工智能 监控
企业官网GEO优化实战:可见性诊断、结构化评分与引用追踪的完整闭环
GEO优化最大的难题是无法度量效果。本文从实际项目出发,搭建一套可落地的AI搜索可见性诊断与度量体系:多引擎关键词覆盖检测与可见性评分模型、内容结构化六维评分表、FAQ Schema配置、AI引用追踪与优化优先级排序,并给出效果验证周期和5个常见踩坑。
|
Rust Kubernetes 负载均衡
Sentinel 2.0:流量治理全面升级
Sentinel 诞生于 2012 年,诞生之初主要为支撑双 11 的限流降级等稳定性场景,后续逐渐在阿里集团内部迅速发展成为基础模块,覆盖了所有流量稳定性的核心场景。
Sentinel 2.0:流量治理全面升级
|
12天前
|
数据采集 人工智能 运维
企业官网GEO是什么?GEO和SEO有什么区别,怎么做官网才容易被AI搜索引用
AI搜索时代,官网不只被"搜得到",还要被"答得出"。GEO与SEO的核心区别一句话:SEO管排名,GEO管AI引用。本文讲清GEO定义、与SEO的六维度对比、AI爬虫放行、llms.txt与JSON-LD配置,附20个站点验证数据和5个踩坑。
|
19天前
|
NoSQL 前端开发 测试技术
商城下单重复扣库存怎么办?订单幂等与库存扣减的数据库实战
结论:商城下单重复、库存对不上,根子大多出在"同一请求被处理两遍"和"扣库存不是原子操作"两处。这篇复盘一次大促中10分钟214条重复订单、库存被扣成-12的故障,讲清幂等键+唯一索引、数据库原子扣减、Redis预扣+对账三层解法,以及5个实战踩坑。
|
23天前
|
缓存 监控 关系型数据库
外卖系统源码:午高峰先加服务器还是加数据库
本文详解外卖系统私有化上线前的午高峰容量评估与扩容策略:强调“先数据库后应用”,聚焦RDS瓶颈识别、无状态扩展、读写分离、缓存设计、导出错峰及监控告警等八大关键点,避免盲目加节点导致超时,助力科学选型与稳定交付。
|
5天前
|
运维 安全 前端开发
网站表单收不到留言?表单数据丢失的定位与三种加固方案
网站表单怎么设置、客户留言怎么收,最怕收不到:前端校验失败、接口重复被拒、落库异常,任一环节都可能悄悄丢线索。先给结论:从前往后加日志定位,再做防重复提交、接口幂等、落库重试三层加固。附可复用代码与五个踩坑。
|
2月前
|
监控 API 调度
发货后物流轨迹“查不到”又“不更新”:快递状态回源的轮询、映射与异常监控实践
结论先说:物流轨迹“查不到”“不更新”,九成不是快递的问题,而是回源查询的设计问题——查询频率不对、状态文案没归一化、异常没有监控。本文复盘一次商城发货模块的物流轨迹改造,讲清轮询策略、状态机映射与异常识别。
|
21天前
|
数据采集 人工智能 JavaScript
"问豆包"哪家好"总搜不到你的官网?企业官网AI搜索可见性(GEO)的排查与改造实战
官网在百度能搜到,问AI却总不带出你?根因是页面缺GEO三层:OG标签(AI识别层)、Schema结构化数据(理解层)、llms.txt(推理层)。本文记录一次企业官网GEO改造:llms.txt从404到生效、JSON-LD从0到3类27项、AI爬虫访问从0到53次、第18天Kimi与豆包带出公司名,附robots放行AI爬虫与四步自测。
|
22天前
|
消息中间件 运维 NoSQL
下单后不付款、库存被一直占用?订单超时自动取消与库存回补的四种方案与踩坑
用户下单后不付款,库存被订单长期占用,前台显示有货却买不了,盘点账实不符。本文对比定时轮询、Redis过期监听、时间轮、MQ延时消息四种超时取消方案,重点讲延时消息加订单状态机的实现,以及取消前二次校验支付状态、库存回补幂等,避免在付款边界误取消已支付订单。