“client closed connection”是客户端主动断开tcp连接所致,核心原因有三类:超时设置冲突(如客户端超时短于nginx keepalive_timeout)、网络或中间设备限制(如nat、防火墙回收空闲连接)、应用逻辑误操作(如未正确处理websocket心跳或返回connection: close)。

客户端浏览器与 Nginx 长连接频繁断开,问题往往不在 Nginx 本身是否“挂了”,而在于它和浏览器之间那条看似稳定、实则脆弱的 TCP 连接,被某一层悄悄切断了。排查要分层推进:先看是哪一端主动关的,再看为什么关,最后确认各层保活节奏是否对齐。
看日志定位断开发起方
Nginx 错误日志(error.log)里出现 client closed connection,说明是浏览器或其所在设备主动发了 FIN 包;若出现 upstream prematurely closed connection,则是后端(如 Go 服务)先断的——此时问题在 upstream 配置;若出现 502 Bad Gateway 或 504 Gateway Timeout,需单独查 upstream 健康状态和超时设置。
- 查 access.log 中对应请求的响应头:如果返回了
Connection: close,说明 Nginx 或上游明确要求关闭连接,不是空闲断连,而是逻辑驱动关闭 - 用
tcpdump -i any port 80 or port 443 -w nginx_disconnect.pcap抓包,过滤 FIN/ACK 包,确认哪一端先发的 FIN
检查客户端侧超时是否过短
浏览器、移动端 SDK 或前端框架自带的连接管理策略,常常比 Nginx 更激进。它们不等 Nginx 超时,自己就先放弃了。
- Chrome 对空闲 HTTP/1.1 连接默认约 5–6 分钟回收;但对 WebSocket,实际受系统 TCP keepalive 影响,可能 30–45 秒就断
- iOS NSURLSession、Android OkHttp 默认空闲连接超时常设为 60 秒左右
- Axios/Fetch 若未配置
timeout,可能依赖底层网络栈行为,尤其在页面跳转、标签页切换时,浏览器会强制 abort 所有 pending 请求
核对 Nginx 与客户端之间的保活参数
Nginx 的 keepalive_timeout 控制 client→Nginx 连接空闲多久后关闭,默认 75 秒。这个值必须 ≥ 客户端侧最短的空闲容忍时间,否则 Nginx 先动手。
- 建议设为
keepalive_timeout 300s;(5 分钟),并同步配置keepalive_requests 1000;防止单连接请求数过多引发异常 - 确保没有在 location 或 server 块中意外覆盖该值,比如写成
keepalive_timeout 10; - 若使用 HTTPS,确认 SSL session reuse 已启用:
ssl_session_cache shared:SSL:10m;和ssl_session_timeout 4h;,避免每次重连都走完整握手
排除中间网络设备干扰
家庭路由器、企业防火墙、运营商 NAT 网关普遍会对空闲 TCP 连接做回收,常见阈值为 60–180 秒。它们不看应用层心跳,只看 TCP 层有没有数据包流动。
- 这类断连通常无明确错误码,表现为偶发 502/504 或直接 WebSocket close code 1006(abnormal closure)
- 解决办法是:在客户端加心跳(如 WebSocket ping/pong)、在 Nginx 启用
proxy_socket_keepalive on;(仅 Linux ≥3.9 有效),并调低系统级 TCP 参数:net.ipv4.tcp_keepalive_time=180 - 注意:
proxy_socket_keepalive只作用于 Nginx→upstream 连接,不影响 client→Nginx;client→Nginx 的 TCP keepalive 由操作系统内核控制,无法通过 Nginx 配置











