CDN 已经接入,静态资源也正常访问,但控制台里的缓存命中率始终不高,源站带宽和请求数没有明显下降。遇到这种情况,不宜直接把缓存时间改成一年。缓存命中率是请求特征、缓存键、源站响应和节点策略共同产生的结果,任何一环不稳定,都可能让看似相同的请求反复回源。
先确认正在观察什么指标
缓存命中率常见的计算方式有两种。请求命中率关注命中的请求次数占比,字节命中率关注由缓存返回的数据量占比。一个站点可能有大量未命中的小型 HTML 请求,同时少量大文件稳定命中,于是请求命中率偏低、字节命中率却较高。反过来,小图片全部命中而大文件持续回源时,请求指标可能很好看,源站流量仍然很高。
排查前要统一时间范围、域名、状态码和资源类型,避免拿全站请求命中率与某个静态目录的字节命中率比较。还应区分 MISS、HIT、BYPASS、EXPIRED、REVALIDATED 等状态。MISS 表示当前节点没有可用对象;BYPASS 通常表示规则明确跳过缓存;EXPIRED 表示对象存在但已经过期;REVALIDATED 则可能发生了条件回源,源站返回 304 后继续使用旧对象。不同 CDN 对状态名称的定义可能不同,应以实际响应头和服务文档为准。
从一个请求的缓存身份开始检查
CDN 判断两个请求能否共用缓存,依赖缓存键。常见组成包括协议、主机名、路径、查询参数,有些配置还会加入 Cookie、请求头、设备类型或地区。只要缓存键中存在高基数变量,同一个文件就会被拆成大量对象。例如图片地址附带随机时间戳,统计参数顺序不断变化,或者把完整 Cookie 纳入静态文件缓存键,都会降低对象被再次访问的概率。
可以挑选一个访问频繁且内容稳定的静态文件,连续请求并比较响应头。下面的命令适用于 Linux,宝塔面板服务器可在 SSH 终端执行。作用是只读取响应头,不修改 Nginx 或站点文件;风险较低,但频繁循环请求可能增加节点和源站访问量,因此不要对生产域名做高并发测试。
curl -sS -I https://www.example.com/static/app.css
curl -sS -I https://www.example.com/static/app.css
验证时关注 Age、Cache-Control、Expires、ETag、Last-Modified、Vary,以及 CDN 提供的缓存状态头。第二次请求若仍是 MISS,不代表缓存系统必然异常,还要确认两次请求是否落到同一节点、该响应是否允许缓存、缓存写入是否完成。该命令没有配置变更,无需回滚;若测试请求影响业务,停止执行即可。
查询参数也应单独验证。业务确认 utm_source、utm_campaign 等参数不影响响应内容后,才适合在 CDN 缓存键中忽略它们。签名、防盗链、图片处理尺寸、语言和版本号等参数通常会改变权限或内容,不能为了提高命中率一概删除。正确做法是建立参数白名单或忽略名单,并保存修改前的规则快照。
源站可能正在禁止缓存
CDN 通常会尊重源站的 Cache-Control。响应包含 no-store 时,对象不应被存储;private 表示响应面向特定用户;no-cache 并非完全不存,而是再次使用前需要验证。Set-Cookie、Authorization、Vary: * 以及部分错误状态也可能触发不缓存策略。WordPress 页面若因插件给所有响应写入登录态 Cookie,即使访客看到的是公共页面,也可能被边缘节点判定为个性化内容。
宝塔环境中,站点 Nginx 配置通常位于 /www/server/panel/vhost/nginx/,主程序常见路径为 /www/server/nginx/sbin/nginx。检查配置前先做只读搜索:
grep -RniE 'expires|add_header[[:space:]]+Cache-Control|proxy_no_cache|fastcgi_no_cache' /www/server/panel/vhost/nginx/
/www/server/nginx/sbin/nginx -T 2>/dev/null | grep -iE 'cache-control|expires|no_cache'
命令适用于安装了宝塔 Nginx 的 Linux 服务器,作用是定位可能影响缓存响应头的配置。风险在于输出中可能包含域名、内部路径或上游地址,不要将完整结果直接发布到公开工单。验证方式是把命中的配置与实际响应头对应起来。命令只读,无需回滚;如果路径不存在,应在宝塔软件商店确认当前 Web 服务是 Nginx、Apache 还是 OpenLiteSpeed,不要照搬路径。
缓存时间不是越长越好
TTL 太短会让热门对象频繁过期,TTL 太长则会放大更新不及时的风险。更稳妥的设计是按内容可变性分层:带内容哈希的 CSS、JavaScript 和图片可以设置较长有效期;文件名固定但偶尔更新的资源使用中等 TTL,并配合版本参数或精准刷新;HTML、接口和用户态页面采用短缓存、条件验证或不缓存。
还要观察请求热度与节点分布。如果一个资源每天只有少量访问,却被分散到大量边缘节点,即使配置完全正确,也可能在每个节点只访问一次,天然难以获得高命中率。预热能够减少首次访问 MISS,但不适合把整个站点无差别灌入节点。低热度对象会很快被淘汰,预热本身也可能制造回源压力。
按可回滚的小步方式优化
-
固定一个基线窗口,记录请求命中率、字节命中率、源站请求数、回源流量、主要状态码和排名靠前的 URL。不要只保存一个百分比。
-
按文件扩展名、目录、查询参数和缓存状态拆分数据,找到 MISS 或 BYPASS 的主要贡献者。优先处理高流量、内容稳定的资源,而不是追求全站统一规则。
-
抽样核对源站和 CDN 响应头,确认缓存键、Cookie、Vary、Set-Cookie、Cache-Control 及错误状态缓存策略。涉及 WordPress 时,应分别测试未登录访客、登录用户、预览链接、购物车和后台路径。
-
每次只修改一类规则,例如先处理无意义查询参数,再调整静态资源 TTL。设置较小的灰度范围,并记录规则编号、修改时间和操作者。
-
观察至少一个完整业务周期,比较命中率的同时检查源站负载、内容新鲜度、错误率和用户态页面。命中率上升但用户看到旧内容,不是有效优化。
验证不能只看控制台曲线
修改后可对同一 URL 连续请求,并追加一个确认会参与缓存键的版本参数,观察新旧对象行为。还应从不同网络或监测点测试,因为单个节点命中不能代表全网。对于 WordPress,发布新文章、更新静态文件、退出登录和加入购物车都应纳入验证,确认公共缓存没有串入用户数据。
常见错误包括强制缓存所有 HTML、忽略全部查询参数、缓存带 Set-Cookie 的响应、把 404 和 500 设置成长 TTL,以及在业务高峰执行全站刷新。全站刷新会让大量对象同时失效,随后集中回源,命中率和源站稳定性可能一起恶化。
回滚与长期建议
变更前应导出或截图 CDN 规则,并备份站点配置。若修改了宝塔 Nginx 配置,先使用 /www/server/nginx/sbin/nginx -t 检查语法,再通过宝塔面板执行重载。该检查命令适用于宝塔 Nginx,作用是验证配置,不会主动重载;风险是输出可能暴露配置路径。验证标准是出现语法正确和测试成功。发生异常时,应恢复备份文件,再次执行语法检查并重载,而不是连续追加临时规则。
CDN 侧出现内容错误、登录态混淆或错误率上升时,应按原规则快照恢复缓存键和 TTL,对受影响 URL 做精准刷新,并暂时绕过存在风险的动态目录。长期维护中,可以为静态资源使用内容哈希文件名,减少刷新依赖;为缓存状态建立分资源类型的监控;将发布系统、缓存规则和刷新动作关联起来。目标不是把命中率推到一个脱离业务的数字,而是在内容正确、用户隔离和源站成本之间取得可验证的平衡。
延伸阅读
