nginx缓存未启动主因是后端非法响应头(如空值、控制字符、多余空格)导致解析失败,触发“upstream sent invalid header”错误,使$upstream_cache_status为空或bypass;需通过error_log定位、curl+xxd查原始字节、log_format调试变量验证,并精准用proxy_ignore_headers忽略问题头,配合proxy_cache_valid强制生效。

排查 Nginx proxy_cache 因后端响应头被阻断而无法缓存,核心是确认响应头是否“合法可解析”——Nginx 不是拒绝缓存,而是压根没成功读完响应头,导致缓存逻辑根本没启动。
看日志:确认是否触发 invalid header 报错
Nginx 遇到非法响应头(如含控制字符、空值、多余空格)时,会在 error_log 中明确报错:
- 搜索
upstream sent invalid header或invalid cache control - 若出现该错误,说明响应头解析失败,
$upstream_cache_status永远不会是HIT/MISS,而是空或BYPASS - 配合
log_format加入调试字段,例如:log_format debug_cache '$remote_addr "$request" $status $upstream_http_cache_control $upstream_cache_status';
观察$upstream_http_cache_control是否为空、含乱码(如\x20)或格式异常(如max-age=后无数字)
抓原始响应:用 curl + xxd 定位异常字节
不要只看 curl -I 的美化输出,它会自动过滤或转义问题字符:
- 执行:
curl -v https://your-api/ 2>&1 | xxd - 重点检查状态行(
HTTP/1.1 200 OK)之后、第一个空行之前的内容 - 查找
\r\n\r\n前是否夹杂\x00、\xa0、\r单独出现、连续空格等 - 常见雷区:后端返回
Cache-Control: public, max-age=(末尾空格)、ETag: "abc\ndef"(含换行)、X-Debug-Info: {...}(超长 JSON 字符串)
验证缓存是否真正进入写入阶段
很多问题表面是“没缓存”,实则是“连缓存入口都没进”:
- 检查
/var/cache/nginx/下是否有对应请求的缓存文件生成(按 MD5 哈希命名) - 若完全无文件,且日志有 invalid header,基本锁定为响应头污染
- 若文件存在但内容不全(
ls -l看大小异常小),可能是响应体被截断,需查proxy_buffer_size是否过小 - 临时加
add_header X-Cache-Status $upstream_cache_status;,若响应中始终没有该头,说明缓存模块未参与处理
针对性修复:忽略非法头,而非全局禁用
不要直接 proxy_ignore_headers Cache-Control Expires ETag,应最小化干预:
- 只忽略已确认出问题的头,例如:
proxy_ignore_headers Cache-Control Expires; - 必须放在
location块内、proxy_pass之后,确保作用域精准 - 同步用
proxy_cache_valid 200 302 10m;显式定义缓存时间,覆盖后端错误指令 - 若
Set-Cookie是干扰项且响应本身可缓存,加proxy_ignore_headers Set-Cookie;并配proxy_hide_header Set-Cookie;阻断透传











