nginx需识别并过滤不可靠后端缓存头,通过proxy_ignore_headers精准忽略非法cache-control/expires,配合proxy_cache_valid显式设缓存规则,保留清洗后的etag/last-modified,并防止多层缓存污染。

后端返回的缓存标识(如 Cache-Control、Expires、ETag)与 Nginx 本地缓存策略不一致时,会导致缓存行为失控:该缓存的没缓存,不该缓存的却被长期命中,甚至出现响应错乱。核心不是“谁优先”,而是“谁可信”——Nginx 必须能识别、过滤、覆盖不可靠的后端头,同时保留真正可用的缓存信号。
识别冲突来源:先看头,再看日志
不要凭经验猜,直接验证:
- 用
curl -I http://your-api/endpoint查看原始响应头,重点关注Cache-Control是否含no-cache、no-store、max-age=0或非法值(如max-age=后无数字) - 检查
ETag是否带引号、是否含空格或控制字符;Last-Modified时间是否为未来时间或明显异常 - 查 Nginx
error_log,搜索upstream sent invalid header或invalid cache control,确认是否因格式错误被整体丢弃 - 查
access_log中$upstream_cache_status字段,若大量为BYPASS或MIS,说明 Nginx 主动放弃了后端头
精准忽略非法头,不一刀切
proxy_ignore_headers 不是屏蔽所有缓存头,而是有选择地让 Nginx “视而不见”,从而启用你配置的兜底策略:
- 只忽略明确出问题的头,例如:
proxy_ignore_headers Cache-Control Expires;(不要加ETag,除非它真含非法字符) - 必须放在
location块内、proxy_pass之后,且仅对该路径生效 - 配合
proxy_cache_valid显式定义缓存规则,例如:proxy_cache_valid 200 302 10m;,覆盖后端的错误指令 - 注意:该指令对
Set-Cookie也有效,若后端误塞了 Cookie 头干扰缓存,可一并忽略
保留并校验可信缓存信号
有些头值得信任,但需清洗后再用:
- 对
ETag,先关默认生成:etag off;,再用add_header ETag "W/\"$(md5sum $request_filename | cut -d' ' -f1)\"";(需 OpenResty 或预生成)确保多节点一致 - 对
Last-Modified,避免依赖文件系统时间,统一设为构建时间:add_header Last-Modified "Wed, 01 Jan 2025 00:00:00 GMT"; - 若后端返回的
Cache-Control部分有效(如含public但max-age错误),可用 Lua 模块提取并重写,而非全盘忽略
防止缓存层叠加污染
当 Nginx 前还有 CDN 或 Varnish 时,冲突会放大:
- 在 Nginx 回源给 CDN 时,用
proxy_hide_header移除后端的Cache-Control,改由 Nginx 注入标准值,避免 CDN 解析混乱 - 若使用
proxy_cache,确保proxy_cache_valid明确排除错误状态码,例如:proxy_cache_valid 403 1s; proxy_cache_valid 200 304 1h; - 对含用户态的动态接口,用
$http_cookie或$arg_token加入proxy_cache_key,避免不同用户共享同一缓存条目











