关键不是调大所有buffer,而是先区分截断发生在缓存逻辑前(响应头/体被proxy_buffer_size或proxy_buffers截断)还是缓存后(键冲突导致错用缓存体);通过$upstream_cache_status、$upstream_http_content_length及curl实测头长精准定位。

排查 Nginx 中缓存与缓冲区参数冲突导致的响应截断,关键不是“调大所有 buffer”,而是分清问题发生在缓存逻辑之前(响应未完整抵达 Nginx)还是之后(缓存写入/读取阶段出错)。多数所谓“缓存截断”,其实是缓冲区配置不当,让响应在进入缓存流程前就被砍断或污染。
先确认截断是否真的发生在缓存环节
缓存本身不截断数据——它只存储已完整接收的响应。若看到“不完整响应”却有 $upstream_cache_status=HIT,说明缓存体本身是完整的,但客户端拿到的是错的副本(比如键冲突混用了不同用户数据);若始终是 $upstream_cache_status=MISS 或空,甚至日志报 upstream sent invalid header 或 upstream sent too big header,那问题根本不在缓存,而在代理缓冲阶段。
- 加日志字段验证:
log_format main '$remote_addr - $request "$status" $upstream_cache_status $upstream_http_cache_control $upstream_http_content_length';,对比$upstream_http_content_length和实际返回字节数 - 用
curl -v http://your-api/ 2>&1 | grep '^ 查响应头总长,超 4096 字节就大概率触发 <code>proxy_buffer_size不足 - 临时禁用缓存:
proxy_cache off;+proxy_buffering on;,再测响应是否仍不完整——若依旧截断,说明纯属缓冲配置问题
检查 proxy_buffer_size 是否阻断缓存入口
该参数决定 Nginx 能否完整读取响应头。一旦失败,Nginx 连状态码都拿不到,缓存逻辑根本不会触发,直接 502 或静默丢弃。常见于带 JWT、多 Set-Cookie、链路追踪头的后端响应。
- 实测命令:
curl -v https://api.example.com/login 2>&1 | grep '^,结果若 ≥ 4096,必须调大 - 安全设值:测出 5212 字节 → 设
proxy_buffer_size 8k;;测出 28KB → 设32k; - 必须放在
location块内、proxy_pass之前;HTTP/2 场景额外检查http2_max_field_size
验证 proxy_buffers 是否导致缓存体残缺
即使响应头合法,若 proxy_buffers 总容量不足,Nginx 可能只缓存部分响应体——浏览器看到 JSON 缺字段、HTML 白屏、CSV 少行,但日志无报错。
- 查后端 P95 响应体大小(从 access_log 或监控系统获取),设
proxy_buffers 数量 × 单块大小 ≥ P95 × 1.2 - 配套设置
proxy_busy_buffers_size:建议为总 buffer 的 1/4~1/2,且不低于单块大小 - 别设
proxy_max_temp_file_size 0:应设为1024m并确保proxy_temp_path所在磁盘有空间和权限
排除缓存键设计引发的“伪截断”现象
当 Vary 头滥用(如 Vary: User-Agent)或 proxy_cache_key 漏掉关键维度(如身份标识),不同请求会命中同一缓存条目。你看到的“内容缺失”,其实是 A 用户的响应被错误返回给了 B 用户。
- 构造仅
Cookie或Authorization不同的两个请求,用sha256sum对比响应体哈希;若不同,该字段必须进缓存键 - 对需用户隔离的接口,显式加入身份标识:
proxy_cache_key "$scheme$host$request_uri $cookie_token"; - 负载均衡下务必加
$upstream_addr,避免不同后端节点返回差异内容却共用缓存











