nginx 正确透传 websocket 握手需同时配置 proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade 和 proxy_set_header connection "upgrade",三者缺一不可,否则后端收不到升级请求,导致 502 错误。

确认 WebSocket 握手请求是否被正确透传
Nginx 默认按 HTTP/1.0 转发,而 WebSocket 升级需要 HTTP/1.1 及特定头字段。若缺少关键配置,Nginx 会直接转发后关闭连接,上游收不到 Upgrade 请求,自然不响应 101,Nginx 等待超时后返回 502。
检查以下三项是否同时存在:
- proxy_http_version 1.1; —— 必须显式声明,不能依赖默认值
- proxy_set_header Upgrade $http_upgrade; —— 将客户端的 Upgrade 头原样传递
- proxy_set_header Connection "upgrade"; —— 告诉 Nginx 不要改写 Connection 头为 close
三者缺一不可。常见错误是只加了前两项,漏掉第三项,导致 Nginx 自动注入 Connection: close,上游拒绝升级。
验证后端服务是否真正监听并响应 WebSocket 路径
502 表面是代理失败,但根源常在后端未就绪。不要只看进程在不在,要验证它能否处理实际的 /socket.io/ 或自定义路径的升级请求:
- 用 curl 模拟握手:curl -i -N -H "Connection: upgrade" -H "Upgrade: websocket" http://127.0.0.1:3000/socket.io/?EIO=4&transport=websocket(替换为你的后端地址和路径)
- 观察响应状态码:应返回 101 Switching Protocols,而非 200、404 或直接断连
- 检查后端日志:NestJS 需确认
@WebSocketGateway的path与 Nginx location 匹配;Socket.IO 需开启allowUpgrades: true
检查 location 与 proxy_pass 的路径匹配是否引发路由错位
WebSocket 路径对大小写、斜杠、前缀极其敏感。一个配置偏差会导致请求根本没进 WebSocket 处理逻辑,而是落到静态文件或 404 路由,最终触发 502。
典型陷阱:
- location 写成
location /ws { ... },但 proxy_pass 是http://backend/→ 实际转发到/,后端收不到/ws前缀 - location 写成
location /socket.io/ { ... },proxy_pass 却是http://backend/socket.io(缺末尾斜杠)→ 请求变成/socket.io//xxx,后端解析失败 - 后端使用 Socket.IO,默认路径是
/socket.io/,但 Nginx location 写成了location /io/且未做重写 → 请求被丢弃
建议统一用带尾斜杠的 location 和 proxy_pass,例如:location /socket.io/ { proxy_pass http://backend/; }
排查连接建立阶段的底层失败
如果错误日志中出现 connect() failed (111: Connection refused) 或 (110: Connection timed out),说明 Nginx 根本连不上后端,和 WebSocket 协议无关,属于更基础的连通性问题:
- 确认后端监听的是
0.0.0.0:端口,不是127.0.0.1或localhost(尤其在 Docker 或 Windows 中 DNS 解析易出错) - Windows 下 NestJS 若指定独立端口(如 3001)运行 WebSocket,需确保该端口未被防火墙拦截,且 Nginx 配置中 proxy_pass 地址可解析(推荐用 IP 替代 hostname)
- 查看后端启动日志,确认 WebSocket server 已成功 bind 并 log 出类似
Listening on /socket.io/的提示











