Nginx缓存头部更新后仍返回旧内容,如何获取新响应?
问题场景
配置了proxy_cache_background_update on;的Nginx缓存环境中,某API初始响应头为Cache-Control=max-age=7, public, stale-while-revalidate=59,后续上游将同资源的响应头修改为Cache-Control=private, no-cache, must-revalidate,但Nginx持续返回旧的过期缓存内容,无法返回新的不可缓存响应。相关配置如下:
#default_location proxy_cache_background_update on; proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504 http_429; proxy_cache_lock on;
结论
可以实现响应头变更时返回新响应而非过期缓存内容,只需调整Nginx的缓存配置适配上游响应头的变化。
原因分析
当前配置中proxy_cache_use_stale updating指令会让Nginx在后台更新缓存的过程中,继续返回旧的过期缓存内容;同时旧缓存的stale-while-revalidate=59头允许Nginx在59秒内返回过期缓存并后台更新。当上游改为不可缓存的响应头后,Nginx仍遵循原有缓存规则返回旧内容,没有优先获取新的不可缓存响应。
配置调整方案
方案一:移除proxy_cache_use_stale中的updating参数
修改配置如下:
#default_location proxy_cache_background_update on; proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504 http_429; proxy_cache_lock on;
移除updating后,当缓存过期需要更新时,Nginx会等待上游返回新响应,不再返回旧缓存,确保新的不可缓存响应能直接返回给客户端。但此方案可能会增加客户端的等待时间,因为需要同步等待上游响应。
方案二:针对不可缓存响应设置缓存有效期
在对应location中添加proxy_cache_valid指令,明确不可缓存响应的处理规则:
#default_location proxy_cache_background_update on; proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504 http_429; proxy_cache_lock on; proxy_cache_valid private no-cache must-revalidate 0;
该指令让带有private、no-cache、must-revalidate头的响应不被缓存(有效期设为0),同时配合移除updating参数,确保新的不可缓存响应不会被旧缓存覆盖。
方案三:使用缓存跳过指令强制获取新响应
可以通过proxy_cache_bypass或proxy_no_cache指令,根据上游响应头或请求条件跳过缓存:
#default_location proxy_cache_background_update on; proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504 http_429; proxy_cache_lock on; proxy_no_cache $upstream_http_cache_control ~* (private|no-cache|must-revalidate);
当上游返回的Cache-Control头包含private、no-cache或must-revalidate时,Nginx不会使用缓存,直接返回上游的新响应。
内容的提问来源于stack exchange,提问作者Axon

