proxy_send_timeout仅控制nginx向后端发送已收完请求体的超时,仅在非长连接下生效,需据文件大小与后端速率估算,并同步调大client_max_body_size、client_body_timeout及后端限制。

proxy_send_timeout 要设得准,关键不是填个大数字,而是看清楚它管什么、在哪起作用、和谁配合。
它只管一件事:Nginx 把已收完的请求体(比如大文件、长 JSON、Base64 数据)一块块发给后端时,等后端确认接收的耐心程度。
不是客户端上传慢,不是后端处理久,也不是响应返回慢——就盯住“发 body 这一段”是否卡住。
它生效的前提条件
- Nginx 已完整接收客户端的请求体(靠
client_body_timeout和client_max_body_size先把关) - 使用的是非长连接(即每次新建 TCP 连接向后端发数据;若启用了 HTTP/1.1 keepalive 或 HTTP/2,这个值基本不触发)
- 后端没及时回 ACK 或没调用
read()/getInputStream(),导致某次 write 后迟迟无反馈
超时后,Nginx 主动断连,日志出现 upstream prematurely closed connection 或 Broken pipe,返回 502/504。
怎么算出合理值
别拍脑袋写 300 或 0,按实际传输能力估算:
- 假设最大请求体为 2GB,后端稳定接收速率为 5MB/s → 理论传输约 400 秒
- 加上网络抖动、WAF 检测、GC 暂停、磁盘 I/O 延迟等余量 → 建议设为 600 秒(10 分钟)
- 若是普通 API,无大 body → 保持默认 60 秒 即可
- 流式上传或导出接口(如
/api/upload、/export/csv)→ 建议 300~600 秒,写在对应location块里
⚠️ 严禁设为 0:会导致 worker 连接长期占用,积压后引发资源耗尽。
必须同步调整的三项配置
单改 proxy_send_timeout 几乎无效,以下三项必须一起配:
-
client_body_timeout:客户端上传 body 的间隔超时,建议 ≥proxy_send_timeout(如都设 600) -
client_max_body_size:确保 Nginx 允许接收那么大的 body,例如2000m - 后端自身限制:
- Spring Boot:
spring.servlet.multipart.max-file-size和max-request-size - Gunicorn:
--limit-request-body - Node.js:
body-parser的limit选项 - 所有后端值都要 大于 Nginx 设置,否则还没转发就 413 了
- Spring Boot:
推荐配置位置与写法
放在 location 块中,精准控制业务路径,不影响其他接口:
location /api/upload {
proxy_pass http://backend;
proxy_send_timeout 600;
client_max_body_size 2000m;
client_body_timeout 600;
}
如需更直传效果(减少 Nginx 缓冲),可加:
proxy_buffering off;
但要注意:关闭缓冲后,Nginx 不再暂存响应,对后端稳定性要求更高。
验证是否真生效的小技巧
- 用
curl -v观察响应头,确认是Transfer-Encoding: chunked或有明确Content-Length,排除被缓存截断 - 在后端加日志,记录每次
read()时间戳,再比对 Nginxerror.log中upstream prematurely closed connection的发生时刻 - 临时让后端某次接收延迟超过当前值(如
sleep(65)),复现超时再调参验证
不复杂但容易忽略。











