nginx代理websocket失败或断连,主因是未正确配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade和proxy_set_header connection "upgrade"三行,且proxy_read_timeout过小导致连接被主动关闭。

WebSocket 连接在 Nginx 反向代理下直接失败、频繁断开或返回 502/504,基本就是 proxy_http_version、Upgrade 和 Connection 这三项没配对,或者超时值太小被主动踢掉。
location 块里必须加的三行 header 配置
仅靠 proxy_pass 不足以让 WebSocket 握手成功。Nginx 默认用 HTTP/1.0 转发,且不透传升级头,导致后端收不到 Upgrade: websocket 请求,直接返回 200 或 502。
-
proxy_http_version 1.1:强制使用 HTTP/1.1(WebSocket 升级协议的前提) -
proxy_set_header Upgrade $http_upgrade:把客户端带的Upgrade头原样传给后端(值通常是websocket) -
proxy_set_header Connection "upgrade":告诉后端“这不是普通请求,是来升级协议的”,不是"keep-alive"或空值
这三行缺一不可,顺序无关,但必须写在对应 location 块内,不能只放在 server 或 http 块顶层。
proxy_read_timeout 必须调大,否则连接秒断
WebSocket 是长连接,没有请求-响应周期。Nginx 默认 proxy_read_timeout 60,意味着后端 60 秒没发数据,Nginx 就直接断开 TCP 连接——用户看到的就是“突然掉线”“反复重连”。
- 建议设为
proxy_read_timeout 86400(24 小时),或至少 ≥ 客户端心跳间隔 × 3 - 同步设置
proxy_send_timeout 86400,防止后端推送延迟触发断连 -
keepalive_timeout对 WebSocket 无效,不用动它
别信“设成 0 就永不超时”的说法:proxy_read_timeout 0 在部分 Nginx 版本中会导致未定义行为,稳妥起见用大整数。
SSL 环境下 wss:// 必须匹配 listen 443 ssl
前端用 wss://your.com/ws,但 Nginx 配置里只有 listen 80,连接会直接被拒绝,浏览器控制台 Network 面板显示 net::ERR_CONNECTION_REFUSED。
- 确保 server 块监听 443 并启用 SSL:
listen 443 ssl http2(http2可选,不影响 WebSocket) - 证书路径必须正确,且域名匹配;否则握手阶段就会卡在 TLS 层,根本到不了 HTTP 升级
- 后端服务本身不需要处理 HTTPS,Nginx 终止 SSL 后以 HTTP/1.1 转发给它即可
用 curl -i -k -H "Connection: upgrade" -H "Upgrade: websocket" https://your.com/ws 测试,返回状态码必须是 101 Switching Protocols,不是 200、301 或 404。
后端是否响应 101 是最终决定因素
Nginx 只负责转发和协议协商,真正完成 WebSocket 握手的是后端服务。如果 Nginx 配置全对,但浏览器 Network 里 WebSocket 请求状态始终不是 101,问题一定出在后端。
- 检查后端是否监听了正确的端口,且进程存活(
netstat -tuln | grep :8080) - 确认后端框架支持 WebSocket 升级(如 Node.js 的
ws、Python 的websockets、Spring Boot 的@EnableWebSocket) - 自研 HTTP 服务需手动解析
Sec-WebSocket-Key并返回标准响应头,包括Sec-WebSocket-Accept
最容易被忽略的一点:Nginx error log 里出现 upstream prematurely closed connection,90% 是后端崩溃或没监听,而不是 Nginx 配置问题。











