nginx代理websocket频繁断开主因是proxy_read_timeout默认60秒,需在精确匹配的location块中显式设为≥3600的正整数,并配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade"、proxy_buffering off和gzip off。

WebSocket 在 Nginx 后频繁断开,绝大多数情况不是后端或前端代码问题,而是 Nginx 未正确识别和维持长连接。排查要从握手是否成功、链路是否被中途截断、日志是否暴露关键线索三方面入手。
看浏览器 Network 面板确认握手状态
打开开发者工具 → Network → Filter 输入 ws 或 wss,找到 WebSocket 连接请求:
- 响应状态码必须是 101 Switching Protocols;出现 200、400、403、502、504 表示握手失败,说明 Upgrade 流程没走通
- 检查请求头:必须含
Upgrade: websocket和Connection: Upgrade - 检查响应头:必须含
Upgrade: websocket和Connection: upgrade;缺任一,说明 Nginx 没透传或后端没响应升级
用 curl 模拟握手验证 Nginx 转发行为
在服务器本地执行命令,绕过浏览器和 TLS 层,直击 Nginx 代理逻辑:
curl -i -N \ -H "Connection: Upgrade" \ -H "Upgrade: websocket" \ -H "Sec-WebSocket-Version: 13" \ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \ http://your-domain.com/ws/
- 响应中必须同时出现
HTTP/1.1 101 Switching Protocols、Upgrade: websocket、Connection: upgrade - 若返回 200 或 404,说明 location 块未生效或路径匹配错误
- 若返回 502,常见于后端服务未启动、proxy_pass 地址不可达,或 Connection 头被覆盖
查 Nginx 错误日志定位具体失败点
启用详细日志(在 http 或 server 块加 error_log /var/log/nginx/error.log debug;),然后搜索关键词:
-
upstream prematurely closed connection:后端提前关闭,但更大概率是 Nginx 自己因proxy_read_timeout到期主动断开 -
client closed connection:客户端断开,需结合前端心跳日志判断是否因超时未响应导致 -
no live upstreams或connection refused:后端不可达,检查proxy_pass地址与端口 - 无报错但连接仍断:重点怀疑
proxy_buffering on(造成帧粘包)、gzip on(破坏二进制帧)或 TCP 中间设备(如云 LB)二次超时
检查配置是否落在正确的 location 块内
所有 WebSocket 关键配置必须写在精确匹配的 location 块中,不能只放在 http 或 server 级别:
- 路径匹配要严格:用
location /ws/ { },避免location / { }或带rewrite的规则干扰请求头 - 必须包含且仅在此块中设置:
proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade" -
proxy_read_timeout必须显式设为 ≥ 3600(建议 86400),设为 0 无效,会退回到默认 60 秒











