截断需先区分响应头或响应体:查日志(upstream sent too big header)、curl对比、$upstream_http_content_length比对、tcpdump抓包定位;响应头过大则调大proxy_buffer_size。

核心是分清截断发生在响应头(Header)还是响应体(Body),再针对性调参。盲目堆大缓冲值反而可能掩盖真实瓶颈,甚至引发忙缓冲区卡死、TCP窗口收缩等问题。
先定位到底是哪部分被截断
不查日志和实测就改配置,容易走偏:
- 看错误日志:出现 upstream sent too big header → 响应头超限,问题在
proxy_buffer_size - 用 curl 对比:执行
curl -i http://your-api/ | wc -c,再直连后端对比字节数;明显偏短且无报错 → 响应体被截断 - 加日志字段:在
log_format中加入$upstream_http_content_length,与实际返回长度比对,差值就是截断量 - 抓包验证:用
tcpdump -i lo port 80观察 TCP payload 是否卡在 4K、32K 等整数边界,可确认是否为缓冲硬限制
响应头过大:精准调大 proxy_buffer_size
该参数只管响应头,必须完整读完才能拿到状态码和后续控制信息。默认 4k 在现代应用中普遍不够:
- 实测响应头总长:运行
curl -v http://your-api/ 2>&1 | grep '^,结果含状态行和所有 CRLF - 按实测值向上取最接近的 2 的幂次:测出 5212 字节 → 设为
8k;测出 28KB → 设为32k - 必须写在
location块内,且位于proxy_pass之前 - 若用 HTTP/2,额外检查
http2_max_field_size(默认也是 4k),它独立限制单个 Header 字段长度
响应体过大:合理扩容 proxy_buffers 与 busy_buffers_size
这是响应体缓冲主力,关键不在“堆内存”,而在匹配业务节奏:
- 参考后端 P95 响应体大小:设
proxy_buffers 数量 × 单块大小 ≥ P95 × 1.2。例如 P95 是 400KB →proxy_buffers 16 32k(512KB 总量) -
proxy_busy_buffers_size必须配套设置:建议为总量的 1/4~1/2,且 ≥ 单块大小。如上例中推荐设为256k或512k - 确保
proxy_buffering on(默认开启,但 location 内可能被覆盖) -
proxy_max_temp_file_size别设为 0:建议设为1024m,并确认proxy_temp_path所在磁盘有足够空间和正确权限
防传输中断:同步调整超时与流式节奏
后端已发数据,Nginx 却“停着不收”,本质是忙缓冲区满导致 TCP 窗口收缩:
-
proxy_send_timeout控制两次向客户端发送数据的间隔,不是总耗时。后端每 30 秒 flush 一次 → 设为45s;SSE 或导出类接口建议300s -
proxy_read_timeout必须 ≥proxy_send_timeout,否则还没传几块就被整体掐断 - 若后端支持流式响应(如分块 HTML、日志流),且 Nginx 缓冲始终成为瓶颈,可考虑在特定 location 关闭缓冲:
proxy_buffering off,但需权衡性能与可控性











