发布时间:2026-09-20 12:31 更新时间:2026-09-20 12:31 阅读量:0
后台上传视频、备份包或者批量导入 Excel 时,页面卡住不动,控制台要么直接返回 413 Request Entity Too Large,要么传到一半报超时。很多站长第一反应是去查带宽和磁盘,其实这类问题绝大多数出在 Nginx 自身的请求体限制和超时参数上。这篇文章按排查顺序把相关参数讲清楚,配置可以直接照着改。
Nginx 默认对客户端请求体有一个上限,超过上限的请求会在还没有转给后端之前就被拒绝,返回 413。这个上限由 client_max_body_size 控制,默认值通常是 1m。注意它对整个请求体生效,包括表单里的文件部分,所以哪怕后端 PHP 的 upload_max_filesize 调到了 100M,Nginx 这一层不放行照样进不去。
先确认当前生效值。Nginx 的配置可能是多层的,http、server、location 都可以设置,就近覆盖,用下面的命令查看编译参数和实际配置文件位置,再逐层核对:
nginx -V
nginx -T | grep -n "client_max_body_size"
nginx -T 会输出合并后的完整配置,配合 grep 能直接看到哪一层写了这个指令、写成了多少。如果确认没有配置,就在需要上传的 server 或 location 里显式声明。下面是一个上传接口的示例,把请求体放宽到 200M,同时把请求体先缓存到磁盘,避免大文件占满内存:
server {
listen 80;
server_name upload.example.com;
client_max_body_size 200m;
location /api/upload {
client_body_buffer_size 1m;
client_body_temp_path /var/cache/nginx/client_temp;
proxy_pass http://127.0.0.1:8080;
}
}
这里有个容易忽略的点:client_body_buffer_size 是内存缓冲区,超出部分会落盘到 client_body_temp_path。如果这个目录所在分区空间不足,或者 Nginx 运行用户对它没有写权限,上传大文件时同样会失败,日志里常见的是写入临时文件相关的报错。改完配置记得用 nginx -t 校验语法,再 nginx -s reload 生效。
413 解决之后,第二个常见症状是上传进度条走到一半停住,最后报 504 或者连接被重置。这通常和超时有关。上传过程中数据是持续在传的,Nginx 用 client_body_timeout 判断两次读操作之间的间隔,默认 60 秒;如果客户端在弱网下停顿超过这个时间,连接会被关掉。反向代理场景还要看 proxy_read_timeout、proxy_send_timeout 和 send_timeout,它们分别约束与后端读、写以及向客户端发送响应的间隔。
需要强调的是,这些超时是“两次 I/O 之间的间隔”,不是整个请求的总时长。所以只要数据在持续流动,慢速上传一般不会触发;真正被卡掉的是长时间没有新数据的场景,比如后端在接收完之前一直不响应。
location /api/upload {
client_max_body_size 200m;
client_body_timeout 300s;
send_timeout 300s;
proxy_pass http://127.0.0.1:8080;
proxy_connect_timeout 10s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off;
}
proxy_request_buffering off 值得单独说一句:默认情况下 Nginx 会先把整个请求体收完再转发给后端,大文件就会先落盘、再转发,整体耗时变长,临时目录压力也大;关闭缓冲后数据边收边转,适合大文件直传后端接口。代价是后端要能持续接收,且 Nginx 无法在转发前就拒绝超大请求,所以 client_max_body_size 依然要设对。具体行为以官方文档为准。
遇到上传失败,建议按下面的顺序定位,避免来回改配置:
先看 Nginx 错误日志,确认是 413 还是超时,两者定位方向完全不同。日志路径一般在 /var/log/nginx/error.log,也可以在配置里单独为上传站点指定。然后用 curl 绕过浏览器做一次最小复现,排除前端分片逻辑的干扰:
curl -v -X POST \
-H "Content-Type: application/octet-stream" \
--data-binary @bigfile.bin \
-o /dev/null \
https://upload.example.com/api/upload
如果 curl 也报 413,说明就是 Nginx 限制;如果 curl 通过而浏览器失败,多半是前端分片或跨域问题。接着检查后端自身的限制:PHP 看 upload_max_filesize 与 post_max_size,后者要大于前者,还要大于实际请求体;Tomcat、Spring Boot 等也有各自的 multipart 限制;某些语言框架还会限制请求体读取长度。这些值要和 Nginx 的 client_max_body_size 保持一致或更大,否则请求过了 Nginx 却在后端被拒。
最后确认磁盘和临时目录:df -h 看 client_body_temp_path 所在分区剩余空间,du -sh 看临时目录是否堆积了未清理的旧文件。Nginx 异常退出时可能残留临时文件,占着空间不释放,需要人工确认后再清理。整个链路是 Nginx 限制 → 超时参数 → 后端限制 → 磁盘空间,一层层往下排,基本不会漏。生产环境改动前建议先在测试环境验证,参数值结合自身带宽和文件大小来定,不要盲目照搬。
| 📑 | 📅 |
|---|---|
| 服务器网卡多队列与中断绑定入门:RPS、RSS 与 irqbalance 怎么取舍 | 2026-09-20 |
| Linux时间与时区排查:date、timedatectl与容器时区一致性 | 2026-09-20 |
| Docker 容器日志写满磁盘:json-file 限制与 max-size 配置 | 2026-09-20 |
| Nginx 与后端长连接调优:keepalive 与 upstream 复用 | 2026-09-20 |
| Docker 容器内 CPU 被限流排查:cfs_quota、cpuset 与 top 显示异常 | 2026-09-19 |
| Docker容器缺命令:精简镜像补装与临时容器调试 | 2026-09-20 |
| Nginx location 匹配优先级实战:=、^~、~ 命中顺序验证 | 2026-09-21 |
| Docker 容器健康检查实战:HEALTHCHECK 与 unhealthy 自动重启 | 2026-09-21 |
| MySQL索引失效排查:EXPLAIN执行计划与隐式转换定位 | 2026-09-21 |
| systemd-resolved 与 /etc/resolv.conf 冲突排查 | 2026-09-21 |