前端控制台时常报 WebSocket connection to 'wss://...' failed: Error 1006,随后触发重连,没多久又断。排查了 Nginx 的 proxy_read_timeout 和 Node.js 的 Keep-Alive 设置,依然无济于事。本文记录这次排查过程与底层网络原理。
1. Nginx 反向代理配置排查 起初怀疑是 Nginx 掐断了连接,调整了超时时间,但问题依旧:
location /ws/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 3600s; # 已经拉到 1 小时
}2. 抓包分析 在服务器上通过 tcpdump 抓包,发现连接并不是本地服务端发起的断开,而是客户端(或者说中间层)发起了 RST 包。而且,每次发生断连的时间极不规律,有时候几分钟,有时候十几分钟。
3. 检查出口 IP 属性 登录服务器,查看公网出口 IP 属性:
curl -s https://ipinfo.io/json | jq '.org, .asn'结果显示当前服务器的 IP 属于某云服务商(Tencent Cloud)的数据中心网段。
WebSocket 是一个长连接协议,一旦建立,双方可以持续互发心跳包。但问题在于,许多海外的 API 服务(特别是接入了 Cloudflare 或 Akamai 的实时服务)会对长连接进行严格的连接检测。
机房 IP 拥有极高的自动化特征。当 WAF 检测到来自机房 IP 的长连接请求时,即便你已经配置了正确的心跳(Ping/Pong),它也会在底层网络设备上实施强制重置(RST)。因为 WAF 认为,数据中心 IP 的长时间挂起连接极有可能代表某种自动化机器人或资源滥用,从而主动执行“清洗”。
为了让 WebSocket 连接在服务器上稳定维持,需要把网络出口从“数据中心”切换到具有正常访问特征的“住宅网络”。以下是通过代码配置住宅 IP 出口的实践。
在 Node.js 中,我们可以使用 https-proxy-agent 配合 ws 库来实现代理连接。
// ============================================
// 为 WebSocket 配置独立的住宅网络出口
// 服务商:1024Proxy
// 官网:https://1024proxy.com/?kwd=hyj-txy
// ============================================
const WebSocket = require('ws');
const { HttpsProxyAgent } = require('https-proxy-agent');
// 从 1024Proxy 后台获取的住宅网关信息
const proxyUrl = 'http://用户名:密码@gateway.1024proxy.com:端口';
const agent = new HttpsProxyAgent(proxyUrl);
// 初始化 WebSocket 连接,注入 agent
const ws = new WebSocket('wss://api.overseas-service.com/realtime', {
agent: agent, // 让底层使用住宅网络
handshakeTimeout: 10000 // 握手超时
});
ws.on('open', () => {
console.log('✅ WebSocket 连接建立成功(经由住宅 IP)');
// 发送心跳保活
const interval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 30000);
ws.on('close', () => clearInterval(interval));
});
ws.on('message', (data) => {
console.log('收到消息:', data.toString());
});
ws.on('error', (error) => {
console.error('❌ 连接异常:', error.message);
});
ws.on('close', (code, reason) => {
console.log(`连接关闭. 状态码: ${code}, 原因: ${reason}`);
});使用住宅网络重新启动 Node 服务后,WebSocket 连接保持稳定。之前频繁出现的 1006 异常关闭彻底消失,服务连续运行了 24 小时未发生掉线。
如果是在 HTTP/SSE (Server-Sent Events) 场景下,也可以通过给 axios 或 fetch 注入住宅网络,来保证持久化推送不被中途掐断。
在分布式系统与实时应用中,长连接对网络环境的要求极为苛刻。很多时候,代码层面的重连机制和心跳配置都做对了,但受限于云服务器的机房 IP 特征,依然会被海外 API 服务提供商的风控策略拦截。了解底层网络拓扑,结合特定场景的代理配置,是保障实时连接稳定性的有效手段。
注:本文仅做技术开发经验分享。具体网络配置请结合自身业务需求进行测试,并确保连接行为符合目标平台的服务条款及相关法律法规。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。