WebSocket卡在Pending主因是Nginx未关闭proxy_buffering、未透传Upgrade/Connection头或proxy_read_timeout过短;后端则可能因Tomcat未启用WebSocket、Filter拦截、证书不匹配或请求未达业务层所致。
websocket 显示 pending,基本可以确定:连接请求发出去了,但还没完成 http 升级握手(即没收到 101 switching protocols 响应),问题不在客户端代码逻辑,而在中间链路或服务端配置。
为什么 Nginx 会让 WebSocket 卡在 Pending
Nginx 默认开启 proxy_buffering on,它会把上游响应攒够再发给客户端。而 WebSocket 握手必须实时返回 101 状态码 + Upgrade: websocket + Connection: upgrade 头,缓冲一挡,就卡住不动了。
- 必须显式关闭缓冲:
proxy_buffering off - 必须透传升级头:
proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection "upgrade" -
proxy_read_timeout不能是默认 60 秒——长连接空闲时会被 Nginx 主动断开,建议设为86400(24 小时) - 如果启用了缓存(
proxy_cache),也得关掉,否则可能缓存握手响应,导致后续连接复用错误响应
为什么 Tomcat 或后端服务会导致 Pending
不是所有 Pending 都是 Nginx 搞的。当浏览器控制台显示 Pending,且你确认 Nginx 配置无误,就要查后端是否真正响应了升级请求。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- Tomcat 进程僵死、线程池耗尽、或某个 Filter(如 Shiro)拦截了
/ws路径——开发环境有 session,真机访问没 session,就被静默拦在门外 - Spring Boot 内嵌 Tomcat 默认不启用 WebSocket 支持,需确认是否添加了
@EnableWebSocket或配置了ServletWebServerFactory - 证书不匹配:用
https://页面连ws://会被浏览器直接拒绝;连wss://但服务端证书(如wss.pem)过期或域名不一致,也会卡在 Pending - 检查后端日志:有没有打印出 WebSocket 握手的 trace 日志?没有,说明请求根本没进到业务层,大概率被前置组件(网关、Filter、SSL 终结点)截断
如何快速定位 Pending 发生在哪一层
别猜,分段验证:
- 绕过 Nginx,用
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://localhost:8080/ws直连后端——如果返回 101,说明后端 OK,问题在代理层 - 在 Nginx access log 中加
$status $upstream_http_upgrade,看是否记录了 101 和websocket值;如果没有,说明 upstream 没返回正确响应 - 用浏览器开发者工具 → Network → 找那个 ws 请求 → 点开 → 查看 Headers → 看 Request Headers 里有没有
Upgrade: websocket,Response Headers 里有没有101和对应头——缺任何一个,就是握手失败 - 用
tcpdump抓包(如tcpdump -i any port 8080 -w ws.pcap),过滤 TCP 流,确认 SYN → SYN-ACK → HTTP GET → 是否收到 101 响应
最常被忽略的是:你以为改了 Nginx 配置就完事,但没重载(nginx -s reload)或没检查配置语法(nginx -t);还有人改了配置却忘了重启 Tomcat,旧进程还在跑,新配置压根没生效。Pending 是个“表面安静、底层断裂”的状态,得一层层剥开看,不能只盯着前端 console。

















