如何测试通过代理建立的 WebSocket 连接

普通 HTTP 探测成功,不代表 WebSocket 工作流可靠。连接可能完成升级,却在后续因代理关闭空闲隧道、重连时出口改变、Worker 未发送心跳、DNS 在错误位置解析,或客户端绕过代理直连而失败。
对于已获授权的聊天、遥测、浏览器自动化、实时价格与应用质量验证,应把 WebSocket 当作完整生命周期测试,而不是只检查一个状态码。有效结果必须证明升级握手、双向流量、连接存活、受控关闭和可预测恢复。
定义唯一测试身份
发送流量前,为每次运行分配非敏感测试编号,并记录:
- 浏览器或客户端版本;
- 代理协议与网关标签;
- 请求地区与出口批次标签;
- DNS 执行方:本地、浏览器、网关或 SOCKS 远程 DNS;
- 地址族;
- 连接开始与结束时间;
- 升级状态、关闭码、消息数量和心跳时间;
- 预期内容标记与最终结论。
不要记录代理密码、Authorization、Cookie、可复用会话令牌或包含个人数据的消息正文。仅使用自己控制或已获授权评估的测试端点。
验证打开握手
标准 WebSocket 先通过 HTTP 请求要求服务器切换协议。应确认:
- 请求确实经过配置的代理;
- 目标主机、端口和协议符合计划;
- 服务器返回有效升级,而不是缓存页、重定向循环、登录页或阻断页;
- 必需的子协议协商成功;
- 代理没有移除升级所需字段;
- 安全 WebSocket 的 TLS 主机名验证仍然正确。
不能因为浏览器显示 socket 已打开就判定通过。使用同一个非敏感测试编号,把客户端时间与代理网关侧记录关联起来。
证明两个方向都能传输
已打开的连接仍可能“半失效”。客户端发送一个小型唯一测试消息,受控服务器必须回显或确认;随后服务器发送独立消息,客户端必须完成内容校验。
记录发送时间、接收时间、方向、字节数和无害消息哈希,原始正文不进入长期日志。先以单并发运行,避免不同连接的消息相互混淆。
若客户端到服务器正常,而服务器到客户端停止,应检查代理缓冲、中间层超时、浏览器或 Worker 生命周期和应用订阅状态。在确定故障边界前不要轮换出口。
测量真实空闲超时
许多代理、负载均衡器和应用网关会关闭安静连接,文档值也可能与实际路径不同。
使用阶梯测试:
- 建立并验证连接;
- 让应用保持 15 秒静默,再发送探测;
- 依次测试 30、60、120 和 300 秒;
- 记录第一次探测或确认失败的间隔;
- 在同一出口批次重复边界区间。
安全的应用心跳间隔必须短于最低可复现空闲截止值,并为网络抖动和事件循环延迟留出余量。不要为了保持所有隧道而设置过于激进的心跳;在大规模任务中,不必要心跳会放大带宽与负载。
区分协议 Ping/Pong 与应用心跳
部分客户端暴露 WebSocket ping/pong 帧;浏览器 JavaScript 通常依赖应用层消息。测试记录必须标明具体机制。
心跳测试需验证三件事:
- 心跳确实通过代理离开客户端;
- pong 或应用确认在截止时间前返回;
- 确认缺失时,连接会被关闭或隔离,而不是作为僵尸连接留在池中。
延迟使用单调计时器,墙上时钟只用于跨系统关联。系统时间调整不应产生负心跳延迟。
分开测试粘性路由与重连
连接保持打开时路径天然固定,但重连属于新的路由事件。若应用依赖地区、账户状态或上游亲和 Cookie,需要明确重连是复用相同代理会话,还是刻意创建新会话。
运行两种场景:
- 粘性重连:复用批准的会话标识,验证逻辑地区与应用状态保持一致;
- 全新重连:新建会话并标注为新样本,验证应用状态可以安全重建。
不要把两者都称为“重试”。它们回答不同问题。重连使用带随机抖动的指数退避;明确拒绝或限流不能触发快速出口轮换。
验证关闭行为
测试客户端正常关闭、服务器正常关闭、策略拒绝、应用重启、网络中断和代理关闭。记录关闭码,以及对端是否收到关闭握手。
正常关闭应释放浏览器、Worker、代理隧道与应用订阅。异常关闭应进入有界恢复流程,重连后不能留下两个活动订阅。
批准的代理不可用时,客户端必须故障关闭,不能回退到设备直连。IPv4 与 IPv6 需要分别测试,因为一个地址族的代理路径失败时,另一个地址族可能仍可直连。
七项发布矩阵
| 场景 | 单一变量 | 必需证据 |
|---|---|---|
| 基线 | 正常连接 | 有效升级与双向消息 |
| 空闲边界 | 逐步增加静默时间 | 可复现截止值与安全心跳余量 |
| 心跳缺失 | 抑制确认 | 检测并清除僵尸连接 |
| 粘性重连 | 相同代理会话 | 保持预期地区与应用状态 |
| 全新重连 | 新代理会话 | 新路径被标注并重建状态 |
| 代理丢失 | 网关不可用 | 故障关闭且无直连回退 |
| 双栈 | 先 IPv4 后 IPv6 | 每个地址族的路由与 DNS 证据 |
每项重复足够次数,以区分确定性策略与短暂路由故障。结论只能是通过、失败或无法判定,缺失证据不能算通过。
常见排错
升级成功,但连接总在固定时间关闭
测量实际空闲截止值并与心跳时序比较,分别检查代理、负载均衡器、服务器、浏览器 Worker 和 NAT 的空闲策略。
消息只能单向到达
检查订阅状态、代理缓冲、事件循环健康度,以及中间层是否把连接视为空闲。必须使用两个方向的受控消息。
重连后到达错误地区
检查代理会话是否复用、DNS 是否换了解析器,以及新出口批次是否符合请求地区。验证响应内容,而不是只看 IP 标签。
不使用代理时正常,通过代理时失败
比较握手请求、TLS 校验、代理鉴权、目标端口策略和升级字段处理。不要用关闭证书验证作为捷径。
发布检查清单
- 握手与代理侧观察成功关联。
- 双向消息均通过受控内容验证。
- 实际空闲超时经过测量,而非假设。
- 心跳间隔留有余量,确认缺失会清除僵尸连接。
- 粘性重连与全新重连是独立测试。
- 重连使用有界退避与随机抖动。
- 关闭码与资源清理已记录。
- IPv4 与 IPv6 的代理丢失都保持故障关闭。
- 日志不含可复用凭据或不必要消息正文。
- 明确拒绝与限流信号得到尊重。
合规说明
WebSocket 测试不会创造访问权限。仅测试自己控制或已获授权评估的端点和账户。遵守访问控制、应用条款、速率限制、数据最小化要求、隐私义务和明确拒绝信号。不得利用重连或轮换出口规避目标站点决定。
相关 98IP 指南
来源说明:IETF,《The WebSocket Protocol》,RFC 6455;MDN Web Docs,WebSocket API。外部来源 URL 仅保存在内部运营记录中。