仅加 proxy_cache_use_stale updating 不能消除并发回源,必须同时启用 proxy_cache_background_update on、proxy_cache_lock on 和明确的 proxy_cache_valid;还需确保 cache key 稳定、后端支持无认证子请求,并通过响应头和日志验证效果。

只加 proxy_cache_use_stale updating 不能消除并发回源。它只是个“通行证”,告诉 Nginx “当缓存正在后台更新时,允许返回旧内容”,但本身不触发更新、也不阻止多个请求同时回源——必须搭配三项关键配置,才能让过期瞬间的请求安静下来。
必须同时启用的三个指令
缺一不可,漏掉任意一个,updating 就不会生效:
-
proxy_cache_background_update on;:这是后台刷新的开关。没有它,Nginx 永远不会发起子请求去拉新数据,“updating 状态”根本不会出现。 -
proxy_cache_lock on;:防止同一缓存 key 的多个请求在过期临界点“撞车”。开启后,只让第一个请求触发后台更新,其余直接复用旧缓存(或走 stale)。 -
proxy_cache_valid明确设置:例如proxy_cache_valid 200 302 30s;。没有这个,Nginx 就不知道什么叫“过期”,也就无法判断何时该进入 updating 状态。
cache key 必须稳定,否则锁和更新都失效
如果 key 不一致,每个请求都会生成独立缓存条目,锁形同虚设,后台也只刷其中一个,其余仍会集体回源:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 避免默认 key 含
$args、$cookie或时间戳等动态字段。 - 推荐写法:
proxy_cache_key "$scheme$host$request_uri";(忽略 query 参数差异)。 - 若需更严格统一,可进一步剥离参数:
proxy_cache_key "$scheme$host:/api/list";。
后台子请求有特殊行为,需后端配合
子请求由 Nginx 自动发起,但它不带原始请求头(如 Cookie、Authorization),且不计入限流:
- 确保后端能接受无认证的刷新请求,否则子请求失败,缓存长期 stale。
- 子请求失败不会重试,建议补充
proxy_cache_use_stale error timeout http_500;作为兜底。 - 锁超时建议设为后端 P95 响应时间,常见值是
proxy_cache_lock_timeout 5s;;太短易放弃锁,太长会导致用户卡顿。
验证是否真正起作用
别只看配置,从响应头和行为确认:
- 加响应头:
add_header X-Cache-Status $upstream_cache_status;。 - 停掉后端服务,发请求:若看到
X-Cache-Status: STALE且响应极快(几十毫秒),说明机制已跑通。 - 观察日志:高峰期
HIT和STALE显著上升,MISS和EXPIRED大幅下降,即代表并发回源已被抑制。










