💓 博客主页:瑕疵的CSDN主页
📝 Gitee主页:瑕疵的gitee主页
⏩ 文章专栏:《热点资讯》
WebSocket断连?心跳包没发对,我差点把服务器干爆!
目录
- WebSocket断连?心跳包没发对,我差点把服务器干爆!
- 报错现场:连接像过山车,5分钟一断
- 核心根源:服务器在等心跳,你却在发呆
- 解决代码:30秒发个心跳包,稳如老狗
- 避坑总结:这些坑我全踩过
报错现场:连接像过山车,5分钟一断
昨天上线的实时聊天功能,用户疯狂投诉“连不上”。控制台疯狂刷:
WebSocket connection to 'wss://xxx' failed: Error in connection establishment: net::ERR_CONNECTION_RESET断连时间点精准得像闹钟——每5分钟整。我盯着日志,头发都薅秃了:服务器明明开着,为啥连不上?
核心根源:服务器在等心跳,你却在发呆
别被“WebSocket”名字骗了。服务器(比如Nginx)默认超时15分钟。没心跳包?服务器直接把你踢下线。
我查了Nginx配置:proxy_read_timeout 15m。客户端没发心跳,服务器一拍大腿:这玩意儿没响应,关了!
(真想骂一句:文档写“支持长连接”,结果连心跳都不给个例子!)
解决代码:30秒发个心跳包,稳如老狗
问题代码(坑爹版):
constws=newWebSocket('wss://api.xxx.com');ws.onopen=()=>console.log('连接成功');// 只管连,不管活修复代码(真香版):
constws=newWebSocket('wss://api.xxx.com');letheartbeatTimer;// 心跳计时器// 连接成功启动心跳ws.onopen=()=>{console.log('连接稳了,开始发心跳');// 每30秒发一次心跳包(别用15秒,服务器可能扛不住)heartbeatTimer=setInterval(()=>{// 确保连接是OPEN状态再发if(ws.readyState===WebSocket.OPEN){ws.send('ping');// 发个空字符串就行,服务器会回pong}else{clearInterval(heartbeatTimer);// 连接断了,赶紧停}},30000);// 30秒一次};// 连接关闭时清理心跳ws.onclose=()=>{clearInterval(heartbeatTimer);// 防止内存泄漏console.log('连接断了,心跳也停了');};避坑总结:这些坑我全踩过
别用
setInterval发心跳:
服务器可能在处理心跳,你发太快反而拖垮它。30秒是安全值(Nginx默认超时15分钟,留够缓冲)。必须判断
readyState:
连接断了还在发心跳?内存泄漏警告!修复代码里if (ws.readyState === OPEN)这句是保命符。服务器要支持pong:
如果服务器不回pong,心跳就白发了。检查后端:ws.onmessage = e => e.data === 'ping' && ws.send('pong')。别信“自动心跳”:
有些库(比如Socket.IO)默认有心跳,但原生WebSocket没有。别以为用new WebSocket()就完事了。
最后补一句:心跳包不是发“心跳”字眼,发个空字符串就行。我昨天还被坑在ws.send('heartbeat')上,服务器根本不认——这破文档,写得比我的代码还乱。
现在,用户说“连接稳如老狗”,我终于能睡个整觉了。