中年|Web端即时通讯实践干货:如何让WebSocket断网重连更快速?( 三 )
5.4 小结
综上所述:
1)定时发送心跳包检测的方案贵在稳定 , 能够覆盖所有场景 , 但速度不即时(心跳间隔是固定的);
2)判断网络状态的方案速度快 , 无需等待心跳间隔 , 较为灵敏 , 但覆盖场景较为局限 。
因此 , 我们可以结合两种方案:
1)定时以不太快的频率发送心跳包 , 比如40s/次、60s/次等 , 具体可以根据应用场景来定;
2)然后在网络状态由offline变为online时立即发送一次心跳 , 检测当前连接是否可用 , 不可用的话立即进行恢复处理 。
这样在大多数情况下 , 上层的应用通信都能较快从不可用状态中恢复 , 对于少部分场景 , 有定时心跳作为兜底 , 在一个心跳周期内也能够恢复 。
6、快速重连关键2:快速断开旧连接
通常情况下 , 在发起下一次连接前 , 如果旧连接还存在的话 , 应该先把旧连接断开 。
这样做的目的:
1)一来可以释放客户端和服务器的资源;
2)二来可以避免之后误从旧连接收发数据 。
我们知道WebSocket底层是基于TCP协议传输数据的 , 连接两端分别是服务器和客户端 , 而TCP的TIME_WAIT状态是由服务器端维持的 , 因此在大多数正常情况下 , 应该由服务器发起断开底层TCP连接 , 而不是客户端 。
也就是说:
1)要断开WebSocket连接时 , 如果是服务器收到指示要断开WebSocket , 那它应该立即发起断开TCP连接;
2)如果是客户端收到指示要断开WebSocket , 那它应该发信号给服务器 , 然后等待底层TCP连接被服务器断开或直至超时 。
那如果客户端想要断开旧的WebSocket , 可以分为WebSocket连接可用和不可用两种情况来讨论 。
具体如下:
1)当旧连接可用时 , 客户端可以直接给服务器发送断开信号 , 然后服务器发起断开连接即可;
2)当旧连接不可用时 , 比如客户端切换了wifi , 客户端发送了断开信号 , 但是服务器收不到 , 客户端只能迟迟等待 , 直至超时才能被允许断开 。
超时断开的过程相对来说是比较久的 , 那有没有办法可以快点断开?
上层应用无法改变只能由服务器发起断开连接这种协议层面的规则 , 所以只能从应用逻辑入手 , 比如在上层通过业务逻辑保证旧连接完全失效 , 模拟连接断开 , 然后在发起新连接 , 恢复通讯 。
这种方法相当于尝试断开旧连接不行时 , 直接弃之 , 然后就能快速进入下一流程 , 所以在使用时一定要确保在业务逻辑上旧连接已完全失效 。
比如:
1)保证丢掉从旧连接收到所有数据;
2)旧连接不能阻碍新连接的建立
3)旧连接超时断开后不能影响新连接和上层业务逻辑等等 。
7、快速重连关键3:快速发起新连接有IM开发经验的同学应该有所了解 , 遇到因网络原因导致的重连时 , 是万万不能立即发起一次新连接的 , 否则当出现网络抖动时 , 所有的设备都会立即同时向服务器发起连接 , 这无异于黑客通过发起大量请求消耗网络带宽引起的拒绝服务攻击 , 这对服务器来说简直是灾难(即:服务端雪崩效应) 。
所以在重连时通常采用一些退避算法 , 延迟一段时间再发起重连 , 如下图中左侧的流程 。
本文插图
如果要快速连上呢?最直接的做法就是缩短重试间隔 , 重试间隔越短 , 在网络恢复后就能越快的恢复通讯 。 但是太频繁的重试对性能、带宽、电量的消耗就比较严重 。
如何在这之间做一个较好的权衡呢?
1)一种比较合理的方式是随着重试次数增多 , 逐渐增大重试间隔;
2)另一方面监听网络变化 , 在网络状态由offline变为online这种比较可能重连上的时刻 , 适当地减小重连间隔 。
推荐阅读
- 中年|北斗“一张网”可实现全天候、高精度、自主可控服务
- 中年|Python编程语言有什么独特的优势呢?
- 中年|谈一谈我的十年机械工作经历
- 中年|弹无虚发的背后,国产弹药质量把关人,精密机床都要自叹不如
- 中年|宿迁深圳招商再结硕果,签约项目19个,协议总投资158亿元
- 中年|苹果:已终止Epic Games开发者账号
- 中年|圆满的结局!苹果微信之间不用再二选一,美国政府还是做出让步
- 中年|国家能源集团成功研发矿用卡车能耗制动开关预警装置
- 中年|什么是余压监控系统?余压监控系统如何接线和安装?一篇文章搞懂
- 中年|上线供应链金融、搭建标准质量体系,三全产业伙伴卓越质量联盟正式启动