使用在线终端、实时聊天、监控面板等应用时,有时会遇到页面正常打开,但一直显示“连接中”“连接失败”或频繁掉线的情况。
这些功能可能使用WebSocket长连接。排查时需要区分:是连接一开始就没有建立,还是建立后又断开。本文以Linux服务器和Nginx常见的HTTP/1.1 Upgrade转发方式为例。
一、确认实际连接地址和报错
在浏览器中按F12打开开发者工具,进入“网络(Network)”,选择“WS”筛选项,然后重新触发连接。
记录请求地址、响应状态、发生时间,以及连接断开前是否收到过消息。
重点检查:
-
域名、端口、路径和查询参数是否正确。
-
HTTPS页面是否使用
wss://连接。 -
接口是否需要登录、令牌或指定子协议。
-
请求是否被重定向到了登录页或普通网页。
例如,页面地址为:
https://example.com
对应的WebSocket地址可能是:
wss://example.com/ws
/ws只是示例,必须使用应用实际提供的接口。
常见响应可以这样判断:
| 响应结果 | 优先检查 |
|---|---|
| 101 | 已返回协议升级响应,继续检查消息收发和业务鉴权 |
| 200 | 是否访问了普通页面,或没有进入升级处理流程 |
| 301、302 | 地址跳转、HTTPS识别或登录状态 |
| 400、426 | 握手参数、协议版本及升级请求头 |
| 401、403 | 登录凭据、Origin校验及访问控制 |
| 404 | 接口路径及代理路由 |
| 502、504 | 后端连接、服务状态及超时日志 |
以上是排查方向,具体原因仍需结合响应内容和服务端日志判断。
二、使用curl检查握手响应

在终端执行以下命令,可以辅助检查HTTP/1.1握手:
curl --http1.1 -i -N --max-time 8 \
-H 'Connection: Upgrade' \
-H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' \
-H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
-H 'Origin: https://example.com' \
https://example.com/ws
将域名、路径和Origin替换为实际值。Origin应对应发起连接的页面来源,包含协议、域名和必要的端口,不包含页面路径。
示例Key用于手工诊断,正式客户端会自动生成握手Key。需要Cookie、令牌或子协议的接口,还必须按应用要求补齐,不能直接用无登录信息的测试结果判断服务故障。
正常的升级响应通常包含:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
上述Accept值对应本例中的Key。完整握手还需要校验相关响应头。
如果先收到101,随后到第8秒提示curl超时,可能只是达到了命令设置的测试时限,不能据此认定服务掉线。
这条命令主要检查升级响应,并不完整模拟应用的WebSocket消息、登录流程或心跳。
三、检查Nginx是否转发升级请求头
查看Nginx读取的配置:
sudo nginx -T
找到实际域名和WebSocket请求匹配的配置位置。
以下示例假设接口路径为/ws,后端HTTP服务监听127.0.0.1:8080:
location = /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 120s;
}
其中,Upgrade和Connection请求头需要明确传递给上游,后端才能按预期处理协议升级。
使用时注意:
-
优先修改实际承接该接口的现有配置。
-
保留原有请求头、鉴权及路由设置。
-
location = /ws是精确路径匹配,不匹配/ws/或其他路径。 -
示例
proxy_pass没有附加URI部分,不要随意增加或删除路径。 -
不要直接用这一小段覆盖整份站点配置。
120s仅为读取超时的示例值,需要根据应用心跳和其他代理层的限制调整。

四、确认后端服务和访问条件
如果代理配置看起来正常,继续检查实际后端。
查看本机监听情况:
sudo ss -lntp
确认后端服务已经启动,并且监听地址、端口与Nginx配置一致。
如果需要绕过前置代理测试,可复用第2节的握手命令,将目标改成实际HTTP后端地址,同时按应用要求设置Host、Origin和登录凭据。
测试应在Nginx能够访问后端的网络环境中进行。Docker容器内的127.0.0.1指向容器自身,不一定是宿主机或另一容器。
此外,还要检查:
| 检查位置 | 重点内容 |
|---|---|
| 应用配置 | WebSocket功能是否启用,接口路径是否正确 |
| 登录与鉴权 | Cookie、令牌、会话是否有效 |
| Origin校验 | 实际页面来源是否在允许范围内 |
| CDN、WAF或负载均衡 | 是否支持并允许该连接,是否有拦截记录 |
| 应用外部地址 | 是否正确识别公网域名和HTTPS访问方式 |
如果接口返回403,应先查看具体拒绝原因,再修正配置。
五、连接成功后掉线,检查心跳和超时
如果能够收到101,但连接过一段时间就断开,应重点检查心跳、空闲超时和应用日志。
查看Nginx错误日志:
sudo tail -n 50 /var/log/nginx/error.log
实际日志路径以站点配置为准。
如果出现类似提示:
upstream timed out (110: Connection timed out)
while proxying upgraded connection
说明连接升级后发生了上游超时,需要检查后端是否长时间没有发送数据。
Nginx的proxy_read_timeout限制的是两次读取上游数据之间的等待间隔,并不是WebSocket连接的总存活时间。
处理时建议:
-
由应用实现有效的心跳及响应。
-
心跳间隔小于连接路径上最短的空闲超时。
-
同时核对CDN、负载均衡和应用自身的限制。
-
检查后端是否重启、异常退出或主动关闭连接。
仅客户端持续发送消息,而后端完全没有返回数据,未必能避免Nginx的读取超时。
单纯把超时时间调得很大,也无法修复鉴权失败、程序崩溃或网络中断。

六、检查配置并验证实际功能
修改Nginx配置后,对于使用systemd管理、服务名为nginx的部署,执行:
sudo nginx -t && sudo systemctl reload nginx
配置检查通过后才会执行重载。面板安装、容器部署或自定义路径安装的Nginx,应使用对应实例的检查和重载方式。
随后重新打开应用,验证:
-
握手能够正常完成。
-
登录或设备认证成功。
-
实际消息能够双向收发。
-
连接能保持到原先容易掉线的时间点之后。
-
网络恢复后,应用能够按设计重新连接。
测试时同时观察浏览器和服务端日志,确认没有持续出现相同错误。
常见问题
1. 网站能打开,为什么WebSocket仍然失败?
普通页面请求与WebSocket升级请求的处理方式不同。首页正常,只能说明普通访问可用,不能证明升级请求头、接口路由和业务鉴权都正确。
2. curl返回101,为什么应用仍显示离线?
101只能说明服务返回了协议升级响应。应用可能还需要设备认证、指定子协议、首条登录消息或有效心跳,必须继续验证完整业务流程。
3. 使用WSS,后端也必须配置HTTPS吗?
不一定。常见部署由Nginx处理公网TLS,再通过受信任的内部网络连接HTTP后端。具体方式应根据网络环境和应用要求确定,公网入口的证书及域名仍需正确。
注意事项
修改前备份相关配置,排查时保留故障时间、请求路径和日志片段。需要登录的接口,应使用有效测试凭据,分享材料前隐藏Cookie、令牌和密码。
如果使用莱卡云服务器后仍无法定位问题,可提交工单,提供部署方式、WebSocket路径、握手响应、掉线时间及相关日志,便于进一步排查。