这个坑值得记一笔。nginx 1.24 开了 http2,客户上传 200M 的视频到一半浏览器报 ERR_HTTP2_PROTOCOL_ERROR,换成 http1.1 试同一个文件就正常,服务端日志里只有一条 400。
刚开始盯着「链路上有设备不支持 http2 的某些帧,直接把连接 RST 掉」,折腾了半个多小时,排掉了。
原因不止一个,得分开看。nginx 的 client_max_body_size 小于实际文件,连接被提前掐断;http2 的流被反向代理缓冲影响,大 body 在缓冲区里被截断;后端是 http1.1,nginx 做协议转换时没有正确转发分块 body。
上来先在服务端确认请求有没有到齐
grep -E 'POST /upload' /var/log/nginx/access.log | tail
临时用 curl 走 http2 复现一次
curl -v --http2 -F file=@test200m.mp4 https://demo.lu0.cn/upload
再往下放开 body 大小并调整缓冲
grep -nE 'client_max_body_size|proxy_request_buffering' /etc/nginx/nginx.conf
剩下的就是重载后再用大文件验证一次
nginx -t && systemctl reload nginx
别只看报错消失,验证要多做一步。curl 走 http2 上传 200M 文件返回 200,浏览器上传进度条走完没有报错,nginx error log 里不再出现 PROTOCOL_ERROR。
提醒一点。http2 下大 body 的失败点常在缓冲和超时,不在协议本身;缩小范围时先用 curl 固定协议版本,再逐项放开,别一上来就怀疑客户端。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
