Nginx proxy_cache_use_stale如何让504源站故障时,陈旧缓存自动降级?
- 内容介绍
- 文章标签
- 相关推荐
本文共计868个文字,预计阅读时间需要4分钟。
当源站返回504 Gateway Timeout错误时,Nginx默认会将错误直接传递给用户。但如果你已缓存过该资源,则结果如下:
为什么 504 场景下 stale 能生效
504 是明确的上游网关超时响应,属于 proxy_cache_use_stale 原生支持的触发条件之一。它和 error(连接失败)、timeout(读取超时)不同:504 表示后端已接收请求但未能按时完成,Nginx 收到的是完整 HTTP 响应包(含状态行和头),因此可安全复用历史缓存。
- 只要该 URL 曾成功缓存过(哪怕已过期),且配置了
http_504参数,Nginx 就会在收到 504 时立即返回陈旧副本 - 无需等待后台更新完成,也不依赖
proxy_cache_background_update - 响应速度接近本地磁盘读取,通常在毫秒级,远快于重试或报错
必须配套的基础缓存配置
单独加 proxy_cache_use_stale http_504 不起作用。以下三项是硬性前提:
-
定义缓存区:在
http块中配置proxy_cache_path,例如: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_valid,例如:proxy_cache_valid 200 301 302 10m;(没有这条,Nginx 不知道“多久算过期”,stale 就无从谈起) -
确保缓存键合理:避免因 Cookie、随机参数导致同一资源被拆成多个缓存项,推荐显式设置:
proxy_cache_key "$scheme://$host$request_uri";(忽略 query 中的版本号等干扰参数)
如何验证 504 降级真实生效
不能只看返回码是否变成 200,要确认内容确实来自陈旧缓存:
- 先正常访问一次目标 URL,确认缓存命中(响应头含
X-Cache: HIT或自定义的X-Cache-Status: HIT) - 临时让后端返回 504:可用
iptables -A OUTPUT -p tcp --dport 8080 -j REJECT拦截 upstream 流量,或修改 upstream server 直接 return 504 - 再次请求,检查响应头:
– 状态码应为 200(或其他原始成功码)
–X-Cache-Status应为STALE(需配合add_header X-Cache-Status $upstream_cache_status;)
–Age响应头值应大于s-maxage或proxy_cache_valid设定时间 - 对比 body 内容与故障前一致,说明不是新生成,而是旧缓存复用
生产环境推荐组合写法
针对 CDN 或高可用边缘节点,建议这样写:
-
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
覆盖连接失败、读取超时、后台更新中、以及全部常见网关错误 -
proxy_cache_lock on;
防止缓存失效瞬间大量并发回源压垮源站 -
proxy_cache_background_update on;
允许前台返回 stale 的同时,后台悄悄刷新缓存,下次请求就能拿到新鲜内容 -
add_header X-Cache-Status $upstream_cache_status;
便于监控平台识别当前响应来源(MISS/HIT/STALE/BYPASS)
不复杂但容易忽略
本文共计868个文字,预计阅读时间需要4分钟。
当源站返回504 Gateway Timeout错误时,Nginx默认会将错误直接传递给用户。但如果你已缓存过该资源,则结果如下:
为什么 504 场景下 stale 能生效
504 是明确的上游网关超时响应,属于 proxy_cache_use_stale 原生支持的触发条件之一。它和 error(连接失败)、timeout(读取超时)不同:504 表示后端已接收请求但未能按时完成,Nginx 收到的是完整 HTTP 响应包(含状态行和头),因此可安全复用历史缓存。
- 只要该 URL 曾成功缓存过(哪怕已过期),且配置了
http_504参数,Nginx 就会在收到 504 时立即返回陈旧副本 - 无需等待后台更新完成,也不依赖
proxy_cache_background_update - 响应速度接近本地磁盘读取,通常在毫秒级,远快于重试或报错
必须配套的基础缓存配置
单独加 proxy_cache_use_stale http_504 不起作用。以下三项是硬性前提:
-
定义缓存区:在
http块中配置proxy_cache_path,例如: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_valid,例如:proxy_cache_valid 200 301 302 10m;(没有这条,Nginx 不知道“多久算过期”,stale 就无从谈起) -
确保缓存键合理:避免因 Cookie、随机参数导致同一资源被拆成多个缓存项,推荐显式设置:
proxy_cache_key "$scheme://$host$request_uri";(忽略 query 中的版本号等干扰参数)
如何验证 504 降级真实生效
不能只看返回码是否变成 200,要确认内容确实来自陈旧缓存:
- 先正常访问一次目标 URL,确认缓存命中(响应头含
X-Cache: HIT或自定义的X-Cache-Status: HIT) - 临时让后端返回 504:可用
iptables -A OUTPUT -p tcp --dport 8080 -j REJECT拦截 upstream 流量,或修改 upstream server 直接 return 504 - 再次请求,检查响应头:
– 状态码应为 200(或其他原始成功码)
–X-Cache-Status应为STALE(需配合add_header X-Cache-Status $upstream_cache_status;)
–Age响应头值应大于s-maxage或proxy_cache_valid设定时间 - 对比 body 内容与故障前一致,说明不是新生成,而是旧缓存复用
生产环境推荐组合写法
针对 CDN 或高可用边缘节点,建议这样写:
-
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
覆盖连接失败、读取超时、后台更新中、以及全部常见网关错误 -
proxy_cache_lock on;
防止缓存失效瞬间大量并发回源压垮源站 -
proxy_cache_background_update on;
允许前台返回 stale 的同时,后台悄悄刷新缓存,下次请求就能拿到新鲜内容 -
add_header X-Cache-Status $upstream_cache_status;
便于监控平台识别当前响应来源(MISS/HIT/STALE/BYPASS)
不复杂但容易忽略

