Nginx需识别并过滤不可靠后端Cache-Control头,通过proxy_ignore_headers精准忽略非法头,配合proxy_cache_valid显式设缓存规则,保留清洗后的ETag/Last-Modified,并防止多层缓存污染。

后端返回的 Cache-Control 头常与 Nginx 本地缓存策略冲突,导致该缓存的不缓存、不该缓存的却命中,甚至响应错乱。关键不是“谁优先”,而是“谁可信”——Nginx 必须能识别、过滤不可靠头,同时保留并加固真正可用的缓存信号。
先验证冲突来源,别猜
直接用命令看真实响应:
-
curl -I http://your-api/endpoint查原始头,重点关注是否含no-cache、no-store、max-age=0或格式错误(如max-age=后面没数字) - 检查
ETag是否带非法空格或控制字符;Last-Modified时间是否为未来时间或明显异常 - 翻
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,除非它真含非法字符;Set-Cookie若干扰缓存,也可一并忽略 - 该指令必须放在
location块内、proxy_pass之后,且仅对该路径生效 - 配合
proxy_cache_valid 200 302 10m;显式定义缓存时长,覆盖后端的错误指令
保留并加固可信缓存信号
有些头值得信任,但需清洗后再用:
- 对
ETag,先关默认生成:etag off;,再用add_header ETag ...统一生成(推荐预计算或 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;和proxy_hide_header Expires;移除后端头 - 再用带
always参数的add_header注入标准值:add_header Cache-Control "public, max-age=3600" always; - 确保
proxy_cache_valid明确排除错误状态码,例如不缓存4xx、5xx响应


















