08 WebSocket 心跳重连机制

WebSocket 是一种网络通信协议,它使得客户端和服务器之间的数据交换变得更加简单。最近在项目中使用 WebSocket 实现了一个简单在线聊天室功能,在此探究下心跳重连的机制。

WebSocket

WebSocket 允许服务端主动向客户端推送数据。之前很多网站为了实现推送技术,采用的技术都是轮询,不仅效率低,也浪费了很多带宽等资源。HTML5 定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket 的优势:

  • 较少的控制开销

  • 更强的实时性

  • 保持连接状态

  • 更好的二进制支持

  • 可以支持扩展

  • 更好的压缩效果

WebSocket 最大的优势就是能够保持前后端消息的长连接,但是在某些情况下,长连接失效并不会得到及时的反馈,前端并不知道连接已断开。例如用户网络断开,并不会触发 websocket 的任何事件函数,这个时候如果发送消息,消息便无法发送出去,浏览器会立刻或者一定短时间后(不同浏览器或者浏览器版本可能表现不同)触发 onclose 函数。

为了避免这种情况,保证连接的稳定性,前端需要进行一定的优化处理,一般采用的方案就是心跳重连。前后端约定,前端按一定间隔发送一个心跳包,后端接收到心跳包后返回一个响应包,告知前端连接正常。如果一定时间内未接收到消息,则认为连接断开,前端进行重连。

心跳重连

通过以上分析,可以得到实现心跳重连的关键是按时发送心跳消息和检测响应消息并判断是否进行重连,所以首先设置 4 个小目标:

  • 可以按一定间隔发送心跳包

  • 连接错误或者关闭时能够自动重连

  • 若在一定时间间隔内未接收消息,则视为断连,自动进行重连

  • 可以自定义心跳消息并设置最大重连次数

0x01 初始化

为了方便复用,这里决定将 WebSocket 管理封装为一个工具类 WebsocketHB,通过传入配置对象来自定义心跳重连机制。

食用方式:

0x02 发送心跳包与重连

这里使用 setTimeout 模拟 setInterval 定时发送心跳包,避免定时器队列阻塞,并且限制最大重连次数。需要注意的是每次进行重连时加锁,避免进行无效重连,同时在每次接收消息时,清除最长间隔消息重连定时器,能接收消息说明连接正常,不需要重连。

0x03 实例销毁

最后给工具类加一个销毁方法,在实例销毁的时候设置一个禁止重连锁,避免销毁的时候还在尝试重连,并且清空所有定时器,关闭长连接。

封装 npm 包

到这里,WebSocket 工具类心跳重连功能基本封装完成,可以尝试开始食用。这里将最终完成代码上传到 Github,详见 websocket-heartbeat。并将其封装上传到 npm 以便今后在项目中使用, 有兴趣可以尝试一下 websockethb

安装

引入与使用

属性

属性

必填

类型

默认值

描述

url

true

string

none

websocket 服务端接口地址

pingTimeout

false

number

8000

心跳包发送间隔

pongTimeout

false

number

15000

15 秒内没收到后端消息便会认为连接断开

reconnectTimeout

false

number

4000

尝试重连的间隔时间

reconnectLimit

false

number

15

重连尝试次数

pingMsg

false

string

"heartbeat"

心跳包消息

发送消息

断开连接

Just enjoy it ฅ●ω●ฅ

最后更新于

这有帮助吗?