核心是复用已存在但过期的缓存内容,需配置proxy_cache_use_stale http_500-504、proxy_cache_path、稳定proxy_cache_key、proxy_cache_valid覆盖5xx,并配合proxy_cache_background_update与proxy_cache_lock实现边服务边更新。

要在后端服务报错时返回过期的陈旧缓存,核心不是“让 Nginx 主动造缓存”,而是授权它在特定错误发生时,**复用已存在但已过期的缓存内容**。这需要一整套协同配置,缺一不可。
只启用可信的错误触发条件
后端真正出问题时,最稳定、语义最明确的信号是返回 500/502/503/504 这类 HTTP 状态码。它们由应用层主动发出,说明服务进程仍在但逻辑异常或不可达。
- 推荐写法:proxy_cache_use_stale http_500 http_502 http_503 http_504;
- 不建议加 error 或 timeout:连接失败、读取超时多为瞬时网络抖动,盲目启用 stale 容易掩盖真实可用性,导致本可成功的请求也被降级
- 如需支持“缓存过期中仍可返回旧内容”,必须额外加上 updating,且要同步开启 proxy_cache_background_update on;
确保缓存本身“有得用、找得着、过得了期”
stale 不生成缓存,只复用。如果缓存压根没存进去、键不稳定、或有效期太短,就无旧内容可返。
- 定义缓存区(http 块):proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:512m inactive=3d use_temp_path=off;
- 在 location 中启用:proxy_cache my_cache;
- 使用稳定缓存键:proxy_cache_key "$scheme$host$request_uri";(避免含
$args、时间戳、随机 ID 等) - 关键一步:让错误响应也进缓存 —— 加上 proxy_cache_valid 500 502 503 504 1m;。否则 5xx 响应根本不会落盘,后续 stale 就无内容可复用
配合后台更新与请求锁,实现边服务边恢复
单纯返回旧内容只是托底起点。更优做法是用户无感过渡到新数据。
- proxy_cache_background_update on;:返回 stale 的同时,Nginx 自动发起低优先级子请求拉取新响应并写入缓存;失败不影响当前响应
- proxy_cache_lock on; + proxy_cache_lock_timeout 3s;:同一缓存键只允许一个请求回源,其余直接返回 stale 或刚刷新好的内容,防止并发击穿上游
验证是否真生效,看三件事
停掉后端服务后,别只看状态码是 200,重点确认:
- 响应头中出现 X-Cache-Status: STALE(需提前配置 add_header X-Cache-Status $upstream_cache_status;)
- 响应体内容与故障前完全一致——不是空页、不是 Nginx 默认 502 页面、也不是结构错乱的 JSON
- 响应耗时极低(通常几十毫秒),明显低于平时回源耗时,说明确实绕过了后端











