细说websocket快速重连机制 (2)

综上,定时发送心跳包检测的方案贵在稳定,能够覆盖所有场景,但速度不太可;而判断网络状态的方案速度快,无需等待心跳间隔,较为灵敏,但覆盖场景较为局限。因此,我们可以结合两种方案:定时以不太快的频率发送心跳包,比如40s/次、60s/次等,具体可以根据应用场景来定,然后在网络状态由offline变为online时立即发送一次心跳,检测当前连接是否可用,不可用的话立即进行恢复处理。这样在大多数情况下,上层的应用通信都能较快从不可用状态中恢复,对于少部分场景,有定时心跳作为兜底,在一个心跳周期内也能够恢复。

快速断开旧连接

通常情况下,在发起下一次连接前,如果旧连接还存在的话,应该先把旧连接断开,这样一来可以释放客户端和服务器的资源,二来可以避免之后误从旧连接收发数据。

我们知道websocket底层是基于TCP协议传输数据的,连接两端分别是服务器和客户端,而TCP的TIME_WAIT状态是由服务器端维持的,因此在大多数正常情况下,应该由服务器发起断开底层TCP连接,而不是客户端。也就是说,要断开websocket连接时,如果是服务器收到指示要断开websocket,那它应该立即发起断开TCP连接;如果是客户端收到指示要断开websocket,那它应该发信号给服务器,然后等待底层TCP连接被服务器断开或直至超时。

那如果客户端想要断开旧的websocket,可以分websocket连接可用和不可用两种情况来讨论。当旧连接可用时,客户端可以直接给服务器发送断开信号,然后服务器发起断开连接即可;当旧连接不可用时,比如客户端切换了wifi,客户端发送了断开信号,但是服务器收不到,客户端只能迟迟等待,直至超时才能被允许断开。超时断开的过程相对来说是比较久的,那有没有办法可以快点断开?

上层应用无法改变只能由服务器发起断开连接这种协议层面的规则,所以只能从应用逻辑入手,比如在上层通过业务逻辑保证旧连接完全失效,模拟连接断开,然后在发起新连接,恢复通讯。这种方法相当于尝试断开旧连接不行时,直接弃之,然后就能快速进入下一流程,所以在使用时一定要确保在业务逻辑上旧连接已完全失效,比如:保证丢掉从旧连接收到所有数据、旧连接不能阻碍新连接的建立,旧连接超时断开后不能影响新连接和上层业务逻辑等等。

快速发起新连接

IM开发经验的同学应该有所了解,遇到因网络原因导致的重连时,是万万不能立即发起一次新连接的,否则当出现网络抖动时,所有的设备都会立即同时向服务器发起连接,这无异于黑客通过发起大量请求消耗网络带宽引起的拒绝服务攻击,这对服务器来说简直是灾难。所以在重连时通常采用一些退避算法,延迟一段时间再发起重连,如下图中左侧的流程。

 

细说websocket快速重连机制

如果要快速连上呢?最直接的做法就是缩短重试间隔,重试间隔越短,在网络恢复后就能越快的恢复通讯。但是太频繁的重试对性能、带宽、电量的消耗就比较严重。如何在这之间做一个较好的权衡呢?

一种比较合理的方式是随着重试次数增多,逐渐增大重试间隔;另一方面监听网络变化,在网络状态由offline变为online这种比较可能重连上的时刻,可以适当地减小重连间隔,如上图中的右侧(随重试次数的增多,重连间隔也会变大),两种方式配合使用。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwfdw.html