核心是nginx配置未适配长连接语义,主因包括proxy_read_timeout默认60秒主动断连、upgrade/connection头缺失致websocket握手失败、tcp keepalive未协同系统参数。

排查 Nginx 反向代理长连接断开问题,核心是区分“连接被谁、在哪个环节、因何原因”中断。95% 的案例并非后端服务异常,而是 Nginx 配置未适配长连接语义,导致误判或主动关闭。
看日志关键词快速定位断连类型
Nginx 错误日志(error.log)里的关键词直接指向故障层级:
- upstream timed out 或 Connection timed out → proxy_read_timeout 或 proxy_send_timeout 过短
- upstream prematurely closed connection → 后端提前关闭连接,常见于 Upgrade/Connection 头未透传,WebSocket 握手失败
- Connection reset by peer 或 recv() failed (104) → 中间设备(防火墙/NAT)静默切断,或 TCP keepalive 未生效
- connect() failed (111: Connection refused) → upstream 不可达,属网络或服务进程问题,与长连接无关
检查 WebSocket 必备三要素是否齐备
Go(如 gorilla/websocket)、Node.js 等主流库严格校验 HTTP/1.1 升级流程。缺一不可:
- proxy_http_version 1.1:HTTP/1.0 不支持 Upgrade 机制,必须显式声明
- proxy_set_header Upgrade $http_upgrade:动态透传客户端发起的 Upgrade 请求头
- proxy_set_header Connection '':清空 Connection 头(注意是空字符串,不是 "upgrade"),避免复用旧连接干扰升级
浏览器 Network 面板若看到状态码是 200 或 400 而非 101,基本可锁定此处配置缺失。
验证 proxy_read_timeout 是否合理
该参数控制 Nginx 从 Go 服务读数据的等待时长,默认 60 秒——这正是 WebSocket 空闲 60 秒后必断的根源:
- 必须设为 ≥ 前端心跳间隔 × 2,例如心跳每 30 秒一次,建议设为 60–300 秒
- 设为 0 无效,Nginx 会退化回默认 60 秒
- 仅作用于 Nginx→Go 连接,不影响客户端→Nginx 连接(由 keepalive_timeout 控制)
- 必须放在 location 块内,server 级配置不生效
确认 TCP 层保活是否协同生效
即使应用层心跳正常,中间防火墙仍可能静默切断空闲连接。此时仅调大超时无用,需启用并调优 TCP keepalive:
- 在 upstream 块中开启:proxy_socket_keepalive on
- 配套设置系统参数:net.ipv4.tcp_keepalive_time=180(建议 180–300 秒),否则内核默认 7200 秒才发探针
- 必须搭配 upstream keepalive 池:keepalive 32,否则每次请求新建连接,保活无意义
- 注意:proxy_socket_keepalive 不替代应用层心跳,只用于探测并清理已被中间设备切断的坏连接











