核心是确认空闲期被nginx主动切断:查debug日志中“upstream timed out”锁定proxy_read_timeout;确保该值≥3600且置于location块内,同步配置keepalive_timeout和proxy_send_timeout,并抓包验证fin包出现时机。

排查 Nginx 代理 WebSocket 因超时导致的断连,核心是确认连接是否在握手成功后、空闲期间被主动切断,而不是握手失败或网络中断。关键不在“能不能连上”,而在“能连多久”。
看日志:确认是否超时主动断连
Nginx 默认不记录 WebSocket 断连的详细原因,需开启 error_log 的 debug 级别(临时启用):
- 在 nginx.conf 的
events或http块中添加:error_log /var/log/nginx/error.log debug; - 重启 Nginx 后复现断连,搜索日志中的关键词:
"upstream timed out"、"client closed connection"、"recv() failed"或"Connection reset by peer" - 若看到
upstream timed out (110: Connection timed out) while reading upstream,基本锁定是proxy_read_timeout触发;若出现client timed out (110: Connection timed out) while waiting for request,则是keepalive_timeout生效
查配置:三项超时是否真正生效且匹配
WebSocket 长连接依赖三个超时参数协同作用,必须同时检查是否写在正确的配置层级:
-
proxy_read_timeout必须设在location块内(不能只写在http或server级),值建议 ≥ 3600(1 小时),且不低于后端心跳间隔的 2 倍 -
keepalive_timeout应与proxy_read_timeout数值一致,确保客户端到 Nginx 的 TCP 连接不被提前回收 -
proxy_send_timeout建议同步设为相同值,防止大消息分片发送中途被中断 - 特别注意:若配置中有
rewrite、proxy_redirect或嵌套location,可能导致超时设置未命中目标路径
抓包验证:确认握手头透传与连接生命周期
仅靠浏览器控制台“WebSocket connected”不可信,需用 tcpdump 或 Wireshark 抓取 Nginx 与后端之间的流量:
- 过滤条件:
tcp port and http,观察握手阶段请求是否含Upgrade: websocket和Connection: Upgrade - 握手成功后,过滤
tcp port and not http,查看后续是否有长时间静默(如 >60 秒无数据),之后是否出现 FIN 包——这是 Nginx 主动关闭的铁证 - 对比直接访问后端(绕过 Nginx)的连接时长,若后者稳定而前者固定超时,即可排除后端代码问题
模拟压测:用简单工具验证稳定性
避免依赖前端页面,用命令行工具快速验证:
- 使用
wscat -c wss://your-domain.com/ws建立连接,保持终端打开,等待 2–3 分钟观察是否断开 - 若断开,立即检查 Nginx error.log 是否有对应时间戳的 timeout 日志
- 再尝试修改
proxy_read_timeout 86400后重复测试,对比断连时间点是否延后











