WebSocket连接失败90%因中间层拦截,关键在HTTP握手是否完整抵达后端并返回101响应;Nginx需显式配置proxy_http_version 1.1、Upgrade和Connection头,缺一不可,且须禁用缓存。

WebSocket 连接失败,90% 的情况不是代码写错了,而是握手阶段被中间层(Nginx、防火墙、浏览器策略)直接拦截或拒绝升级。关键不在 new WebSocket() 那行代码本身,而在它发出的 HTTP 请求是否能完整抵达后端并完成 101 Switching Protocols 响应。
为什么 Nginx 反向代理后 WebSocket 一直报 failed?
Nginx 默认把 WebSocket 请求当普通 HTTP 处理,不转发 Upgrade 和 Connection 头,导致服务端收不到升级指令,直接返回 400 或静默断连。
- 必须在 location 块中显式添加:
proxy_http_version 1.1;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade"; - 漏掉任意一项,比如只加了
Upgrade没加Connection "upgrade",照样失败 - 如果用了
proxy_cache,务必关闭——WebSocket 不允许缓存握手响应 - 检查 Nginx 错误日志里是否有
upstream sent no valid HTTP/1.0 header类提示,这是典型配置缺失信号
前端用 wss:// 却提示 net::ERR_CONNECTION_REFUSED 怎么办?
这个错误说明 TCP 层连接就失败了,根本没走到 TLS 握手或 WebSocket 升级阶段。和证书、Token 都无关,先查通路。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 确认后端 WebSocket 服务监听的是 HTTPS 对应的端口(通常是
443),而不是单独开一个8080端口再让 Nginx 转发 wss —— 这种架构下 wss:// 实际仍需走 443 - 用
curl -v https://yourdomain.com测试基础 HTTPS 是否通;再试curl -v -H "Connection: upgrade" -H "Upgrade: websocket" https://yourdomain.com/ws看能否拿到101响应 - 云服务器安全组 / 防火墙必须放行目标端口(443 或你自定义的 wss 端口),仅开放后端应用端口(如 8080)不够
- 本地开发时若用
wss://localhost:8443,确保 Spring Boot 的server.ssl.key-store已正确配置,否则启动失败,自然连不上
Token 放 Header 还是 URL 参数?为什么总认证失败?
WebSocket 握手是 HTTP 请求,但浏览器会剥离大部分自定义 Header(包括 Authorization),只保留协议必需头。Token 放 URL 是最稳妥的传递方式。
- Header 方式失效常见场景:
new WebSocket('wss://api.example.com/ws', { headers: { Authorization: 'Bearer xxx' } })—— 这个headers选项在标准WebSocket构造函数中**根本不支持**,属于某些封装库的扩展,原生 API 无法使用 - 正确做法:把 token 拼进 URL,例如
const socket = new WebSocket('wss://api.example.com/ws?token=' + encodeURIComponent(token)) - 后端必须从
request.query.token(或等效方式)读取,不能依赖Authorization头解析 - 如果非要用 Header,只能靠反向代理(如 Nginx)在转发时注入,例如:
proxy_set_header X-Auth-Token $arg_token;,再由后端读取该自定义头
浏览器控制台只显示 failed,怎么快速定位具体哪一环断了?
别猜,直接看 Network 面板里的 WS 请求详情,重点盯三个字段:Status、Request Headers、Response Headers。
- Status 显示
failed:大概率是 DNS、TCP 连接、SSL 握手失败,检查域名解析、端口连通性、证书有效性 - Status 是
400或401:服务端拒绝了握手请求,查后端日志,看是否校验 Origin、Token、路径失败 - Status 是
101但后续无消息:握手成功,问题出在业务逻辑层(如鉴权通过后未调用conn.Accept(),或消息循环卡死) - Request Headers 缺少
Upgrade: websocket或Connection: Upgrade:前端代码或代理配置有问题,不是后端锅
真正棘手的永远是那些「看起来配置全对,但就是不通」的情况——比如 Nginx 配置里多了一个空格导致指令失效,或者云厂商负载均衡器默认关闭 WebSocket 支持却没在控制台显式提示。这时候不要反复改代码,先抓包看原始请求头是否完整到达后端,比调十次前端更省时间。

















