客户端长连接过早断开主因是Nginx配置与协议语义错配:需检查error.log中“upstream prematurely closed connection”日志,调大proxy_read_timeout/proxy_send_timeout,透传Upgrade/Connection头,关闭proxy_buffering,并验证HTTP/2/TLS参数合规性。

看日志里有没有 “upstream prematurely closed connection”
这是最典型的信号,说明 Nginx 和后端(比如 Go 服务)之间的连接被后端主动或被动关闭了,但 Nginx 还以为它该活着。重点查 /var/log/nginx/error.log,配合 $upstream_addr 和 $request_time 字段定位具体 upstream 节点和耗时模式。
常见诱因包括:
- proxy_read_timeout 太小:WebSocket 空闲期无数据,Nginx 默认 60 秒就断;建议设为前端心跳间隔 × 2.5(如心跳 45s,这里至少 120s)
- proxy_send_timeout 过短:Nginx 向后端发数据卡住超时,也会触发断连,应与 proxy_read_timeout 同量级
- 后端未正确响应 FIN 或未启用 TCP keepalive:连接空闲时系统层先断,Nginx 捕获到 RST 后记录此错误
确认 Upgrade/Connection 头是否透传(WebSocket 场景必查)
如果浏览器 Network 面板看到请求状态是 200 或 400,而不是 101 Switching Protocols,基本就是握手失败。Nginx 默认不转发 Upgrade 和 Connection 头,导致 Go 的 gorilla/websocket 直接拒绝升级。
必须在对应 location 块中配齐:
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";(注意双引号不能省)
漏掉任意一条,都可能造成连接建立后很快中断,或根本升不了级。
检查 proxy_buffering 是否关闭(WebSocket/流式响应关键)
WebSocket 是帧驱动协议,消息必须逐帧实时透传。Nginx 默认 proxy_buffering on 会攒包,把多个小帧合并发送,客户端收到的就是乱序二进制流,gorilla/websocket 解析失败后静默断连或报 websocket: bad write message type。
解决方法很简单:
- 在 location 块中加 proxy_buffering off;
- 确保 proxy_http_version 1.1; 已启用(否则 Connection: upgrade 不生效)
验证 HTTP/2 或 TLS 层是否引发隐性断连
HTTP/2 下出现 ERR_HTTP2_PROTOCOL_ERROR 或连接闪断,常和 TLS 参数有关:
- 确认只在 listen 443 ssl http2 上启用 HTTP/2,80 端口不要加 http2
- 检查 ssl_protocols TLSv1.2 TLSv1.3;,禁用 TLSv1/TLSv1.1
- 增大头部限制:http2_max_field_size 64k;、http2_max_header_size 128k;(防大 Cookie 导致 431)
- 确保 OpenSSL ≥ 1.1.1,Nginx 编译启用了 --with-http_v2_module



















