仅配置 proxy_cache_use_stale updating 无效,必须同时启用 proxy_cache_background_update on、proxy_cache_lock on 和 proxy_cache_valid,三者缺一不可,否则无法消除缓存过期请求风暴。

单靠 proxy_cache_use_stale updating 无法解决缓存过期瞬间的突发回源。它只是“允许返回过期内容”的开关,本身不触发更新,也不阻止并发回源——必须搭配三项关键配置,才能真正把“过期风暴”变成“静默刷新”。
核心机制:不是等,而是边返边刷
缓存过期时的请求风暴,本质是多个请求同时发现缓存失效,争着回源。而正确方案的逻辑是:
- 用户请求一来,Nginx 立刻返回当前缓存(哪怕已过期),响应头标记为 X-Cache-Status: STALE
- 同时,Nginx 在后台悄悄发起一个子请求去上游拉新数据
- 这个子请求不阻塞用户,也不计入限流,更不会被其他请求感知
- 新内容写入后,下一次请求就自然命中 HIT
必须同时启用的三个指令
缺一不可,漏掉任意一个,updating 都形同虚设:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
-
proxy_cache_background_update on;:这是“后台刷新”的启动器。没有它,Nginx 永远不会进入 updating 状态,
updating条件永远不满足 - proxy_cache_lock on;:防止多个请求在同一毫秒撞上“即将过期”的缓存,各自触发一个后台子请求。开启后,只让第一个请求发起刷新,其余直接复用旧缓存
-
proxy_cache_valid 明确设置:例如
proxy_cache_valid 200 302 30s;。没有这个,Nginx 就没有“过期”概念,“即将过期”和“已过期”都无从判断
关键配置细节与避坑点
很多配置看似正确,实则在边界场景失效:
-
cache key 必须稳定:避免默认含
$args或$cookie。同一资源若因参数不同生成多个 key,后台只刷其中一个,其余仍会集体 MISS。推荐:proxy_cache_key "$scheme$host$request_uri"; -
后台子请求不带敏感头:它不会携带原始请求的
Cookie或Authorization。确保后端能接受无认证的刷新请求,否则刷新失败,缓存长期 stale -
锁超时要合理:设
proxy_cache_lock_timeout 5s;。太短(如 1s)会导致等待请求放弃锁、直接回源;太长(如 30s)会让用户明显卡顿 -
兜底 stale 策略要全:加上
error timeout http_500 http_502 http_503 http_504,确保后端挂了、超时了、子请求失败了,用户仍能拿到旧内容
如何验证是否真正生效
别只看配置,用实际响应确认行为:
- 加响应头:
add_header X-Cache-Status $upstream_cache_status; - 停掉后端服务,发请求:如果看到 X-Cache-Status: STALE 且响应极快(远低于
proxy_read_timeout),说明机制已跑通 - 用 ab 或 wrk 并发压测同一 URL:多个请求应几乎同时返回 STALE,而不是一部分 MISS、一部分 502
- 检查 Nginx 日志:应出现
UPDATING或STALE状态记录,而非大量EXPIRED后紧接回源










