浏览器层、CDN层、Nginx层、服务端本地缓存层,每层管好各自的TTL和刷新策略,才能真正把回源压力降下来。实际落地时,多数团队只盯着Nginx配置,忽略了浏览器和CDN的联动规则,结果缓存命中率上不去,动态请求照样把后端打穿,下面按分层顺序拆解每层的规则设计要点、配置文件写法以及常见坑。
动静分离架构下缓存规则怎么设置才不冲突
动静分离的核心逻辑是:静态资源走缓存链路,动态接口走应用服务,但缓存规则如果各层各写各的,很容易出现“浏览器缓存过期了,CDN还在保鲜期”或者“Nginx缓存了动态数据”这类错位问题,设计规则前,先明确每一层的职责边界。
第一层:浏览器缓存规则
浏览器缓存是离用户最近的一层,规则设计目标只有一个:让静态资源在用户本地多待一会儿,通过响应头控制,优先级从高到低是 Cache-Control > Expires > Pragma,推荐静态资源的响应头设置如下:
- 图片、CSS、JS等指纹资源:
Cache-Control: public, max-age=31536000, immutable - HTML页面:
Cache-Control: no-cache(每次都回源验证,但304响应体极小) - 动态接口:
Cache-Control: no-store(禁止任何形式的缓存)
这里有个容易踩的坑:很多团队给HTML也设置了max-age=86400,导致页面更新后用户要等一天才能看到新版本,行业共识是HTML必须走协商缓存,用ETag或Last-Modified让浏览器每次回源问一句“变没变”,变就返回200+新内容,没变就返回304。
第二层:CDN缓存规则
CDN层的缓存规则制定,要从代价角度计算:回源一次要花多少时间,用户等待会流失多少转化,CDN的缓存规则按目录和文件类型区分优先级,具体配置路径为:CDN控制台 → 缓存配置 → 添加缓存规则,常见场景的TTL值参考如下表:
| 文件类型 | CDN缓存时间 | 刷新策略 |
|---|---|---|
| 指纹静态资源(带hash的JS/CSS) | 30天 | 上线时精准刷新 |
| 非指纹图片(logo、背景图) | 15天 | 批量刷新目录 |
| HTML页面 | 0秒(不缓存) | 回源获取最新 |
| 动态接口(api/) | 0秒(不缓存) | 透传回源 |
静态资源文件名的hash策略是这一层的灵魂,文件名不带hash的资源,发布后必须手动刷新CDN缓存,否则用户拿到的是旧文件,带hash的资源则不用管,文件名变了就是新请求。CDN缓存规则落地时要额外加一条:创建cache-control响应头覆盖规则,确保源站没配头的情况下CDN能兜底。
第三层:Nginx应用层缓存规则
Nginx层是动静分离架构的最后一道防线,在CDN后面保护应用服务器,核心需求是:CDN没命中的请求到了Nginx,Nginx能自己扛住一部分重复请求,而不是直接打到Tomcat或Node进程,使用proxy_cache模块实现,关键配置项如下:
# 定义缓存路径和键
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=static_cache:10m max_size=10g
inactive=60m use_temp_path=off;
# 静态资源走缓存
location ~ \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_cache static_cache;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 301 302 30d;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
}
# 动态请求直接透传
location /api/ {
proxy_cache_bypass $http_pragma;
proxy_no_cache $http_pragma;
proxy_pass http://backend;
}
proxy_cache_key的取值设计要特别留意,动静分离架构中,带查询参数的静态资源如果参数不影响内容,键里就别带$args,否则同一个文件不同参数会生成多份缓存副本,白白浪费磁盘空间。add_header配置是为了验证缓存是否生效响应头里能看到HIT还是MISS。
Nginx缓存命中率怎么提升?多数情况下,问题出在缓存键设计不合理,而不是配置本身,排查时先看X-Cache-Status头,如果MISS比例较高,把proxy_cache_key简化为$host$uri试试,QPS能看出明显变化。
第四层:服务端本地缓存规则
Nginx层miss的请求最终到达应用服务,这一层缓存的目标是解决热点问题,比如某条商品详情、某个热门文章,本地缓存用Caffeine或Guava,规则设计遵循两点:单机容量上限和过期策略,推荐配置值:
- 最大容量:10000条(根据堆内存调整,一般不超过JVM堆的5%)
- 写入后过期时间:5分钟
- 访问后刷新时间:10分钟
本地缓存不解决分布式问题,多实例部署时每台机器各存一份,数据一致性靠TTL兜底,热点Key的识别逻辑是:统计每个Key的访问次数,超过阈值就自动拉长TTL,这套规则在电商大促场景中收益最明显详情页QPS从万级降到千级,后端压力直接少一个量级。
动静分离缓存配置常见问题排查
规则设计好了,上线后还是可能出幺蛾子,这里梳理几个高频问题,每个都是实操中真实遇到的场景。
为什么用户看到的内容不是最新的
用户本地缓存过期时间还没到,或者CDN节点缓存未失效,排查顺序是:先看浏览器Network面板的Cache-Control响应头,确认是否设置了no-cache;再问CDN节点刷新记录,验证发布时是否做了精准刷新,多数情况下的根因只有一个:上线流程里漏掉了缓存刷新步骤,解决方式是在发布脚本中加上CDN刷新API的调用,发布即刷新。
动态接口被缓存了怎么办
动态接口被缓存通常是因为Nginx层配置了全局缓存规则,location /匹配到了proxy_cache,而/api/的location优先级不够,检查方法:
- 执行
nginx -T查看完整配置,确认proxy_cache生效范围 - 验证
location /api/的匹配规则是否在静态资源规则之前 - 在接口响应头里加上
Cache-Control: no-cache, no-store
如果接口里的数据是用户维度的,还需要在Nginx层加proxy_no_cache规则,用$cookie_变量判断登录状态,登录用户请求一律不缓存,防止数据串号。
缓存服务器的磁盘和内存占用越来越高
静态资源文件多了之后,Nginx缓存磁盘占用会持续攀升,优化策略有两个方向:一是调低max_size并设置inactive时间,超过60分钟没被访问的文件会被清理;二是减少缓存副本很多场景下同一个文件只是查询参数不同,被复制了好几份,改造proxy_cache_key为只取URI部分,磁盘占用能减少约30%。
动静分离缓存规则上线前怎么验证
规则配好别急着上全量,先做一轮小流量验证,确认缓存命中率和刷新链路都正常再推全。
预期效果验证
在预发环境模拟真实请求,观察响应头和后端日志,验证指标如下:
- 首屏请求静态资源命中
X-Cache-Status: HIT比例高于95% - 动态接口响应头带
Cache-Control: no-store - 发布后访问页面能拿到最新内容,无需手动刷新
回源流量对比
发布前用监控工具记录后端接口的平均响应时间和QPS,上线后对比同一时间窗口的数据,RPS下降说明缓存规则生效,响应时间无明显变化则说明Nginx缓存没接上,需要回头检查proxy_pass的配置。
缓存穿透保护
缓存规则落地后,还要考虑穿透场景:CDN回源时源站挂了,或者热点Key集中过期导致请求雪崩,解决机制在Nginx层配置limit_req限流,在服务端用互斥锁控制缓存重建,保证同一时间只有一个请求去查数据库。
结合真实业务场景来看,动静分离架构中缓存规则的分层设计,本质上是把TTL和缓存键的决策权从“写代码的人”手里交还给“流量特征”,静态资源往长了配,动态请求往短了走,每层的策略都在自己职责内转圈,不回源、不越界,这套规则不区分技术栈,Nginx、OpenResty、Traefik的落地方式大同小异,核心逻辑一致:哪层离用户近,哪层扛大头。
动静分离缓存规则常见问题解答
动静分离缓存规则误伤动态数据后怎么恢复
误伤表现为页面出现旧数据或串号数据,先确认生效范围,如果是用户维度的缓存污染,直接在Nginx配置中加proxy_cache_bypass,用$http_cookie判断登录态并绕过缓存,同时调大proxy_cache_valid的时间窗口,让已有缓存自然过期即可。
移动端和PC端是否要区分缓存规则
推荐区分,移动端的弱网环境需要更长的缓存时间,PC端TTL设短一些、移动端长一些,因为移动端资源体积通常更小,缓存策略也更激进,具体数值建议PC端按标准时间配置,移动端在标准时间基础上延长1.5倍,但刷新策略必须保持一致,避免两端缓存生命周期不同导致内容发布时间差。
缓存规则配置多久后能看到效果
以小时级周期观察,静态资源请求的命中率在配置生效后立即就能看出变化,但全链路收益要等CDN节点的缓存填充完成后才稳定,通常在1小时内,核心指标盯住回源带宽和平均响应时间,两个指标同步下降就能确认分层设计落地成功。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/794683.html


