细说 Websocket 快速重连机制

在一个完善的即时通讯应用中,websocket是极其关键的一环,它为web应用的客户端和服务端提供了一种全双工的通信机制,但由于它本身以及其底层依赖的TCP连接的不稳定性,开发者不得不为其设计一套完整的保活、验活、重连方案,才能在实际应用中保证应用的即时性和高可用性。‘

作者/ 网易智慧企业web前端开发工程师 马莹莹

就重连而言,其速度严重影响了上层应用的“即时性”和用户体验,试想打开网络一分钟后,微信还不能收发消息的话,是不是要抓狂?

因此,如何在网络变更时快速恢复websocket的可用,就变得尤为重要。

快速了解websocet

Websocket诞生于2008年,在2011年成为国际标准,现在所有的浏览器都已支持。它是一种全新的应用层协议,是专门为web客户端和服务端设计的真正的全双工通信协议,可以类比HTTP协议来了解websocket协议。

它们的不同点:

  • HTTP的协议标识符是http,websocket的是ws
  • HTTP请求只能由客户端发起,服务器无法主动向客户端推送消息,而websocket可以
  • HTTP请求有同源限制,不同源之间通信需要跨域,而websocket没有同源限制

相同点:

  • 都是应用层的通信协议
  • 默认端口一样,都是80或443
  • 都可以用于浏览器和服务器间的通信
  • 都基于TCP协议

两者和TCP的关系图:

细说 Websocket 快速重连机制

重连过程拆解

首先考虑一个问题,何时需要重连?

最容易想到的是websocket连接断了,为了接下来能收发消息,我们需要再发起一次连接。但在很多场景下,即便websocket连接没有断开,实际上也不可用了,比如设备切换网络、链路中间路由崩溃、服务器负载持续过高无法响应等,这些场景下的websocket都没有断开,但对上层来说,都没办法正常的收发数据了。因此在重连前,我们需要一种机制来感知连接是否可用、服务是否可用,而且要能快速感知,以便能够快速从不可用状态中恢复。

一旦感知到了连接不可用,那便可以弃旧图新了,弃用并断开旧连接,然后发起一次新连接。这两个步骤看似简单,但若想达到快,且不是那么容易的。

首先是断开旧连接,对客户端来说,如何快速快速断开?协议规定客户端必须要和服务器协商后才能断开websocket连接,但是当客户端已经联系不上服务器、无法协商时,如何断开并快速恢复?

其次是快速发起新连接。此快非彼快,这里的快并非是立即发起连接,立即发起连接会对服务器带来不可预估的影响。重连时通常会采用一些退避算法,延迟一段时间后再发起重连。但如何在重连间隔和性能消耗间做出权衡?如何在“恰当的时间点”快速发起连接?

带着这些疑问,我们来细看下这三个过程。

细说 Websocket 快速重连机制

快速感知何时需要重连

需要重连的场景可以细分为三种,一是连接断开了,二是连接没断但是不可用,三是连接对端的服务不可用了。

名列前茅种场景很简单,连接直接断开了,肯定需要重连了。

而对于后两者,无论是连接不可用,还是服务不可用,对上层应用的影响都是不能再收发即时消息了,所以从这个角度出发,感知何时需要重连的一种简单粗暴的方法就是通过心跳包超时:发送一个心跳包,如果超过特定的时间后还没有收到服务器回包,则认为服务不可用,如下图中左侧的方案;这种方法最直接。那如果想要快速感知呢,就只能多发心跳包,加快心跳频率。但是心跳太快对移动端流量、电量的消耗又会太多,所以使用这种方法没办法做到快速感知,可以作为检测连接和服务可用的兜底机制。

细说 Websocket 快速重连机制

如果要检测连接不可用,除了用心跳检测,还可以通过判断网络状态来实现,因为断网、切换wifi、切换网络是导致连接不可用的最直接原因,所以在网络状态由offline变为online时,大多数情况下需要重连下,但也不一定,因为webscoket底层是基于TCP的,TCP连接不能敏锐的感知到应用层的网络变化,所以有时候即便网络断开了一小会,对websocket连接是不会有影响的,网络恢复后,仍然能够正常地进行通信。因此在网络由断开到连接上时,立即判断下连接是否可用,可以通过发一个心跳包判断,如果能够正常收到服务器的心跳回包,则说明连接仍是可用的,如果等待超时后仍没有收到心跳回包,则需要重连,如上图中的右侧。这种方法的优点是速度快,在网络恢复后能够名列前茅时间感知连接是否可用,不可用的话可以快速执行恢复,但它只能覆盖应用层网络变化导致websocket不可用的情况。

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

快速断开旧连接

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

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

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

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

快速发起新连接

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

细说 Websocket 快速重连机制

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

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

除此之外,还可以结合业务逻辑,根据成功重连上的可能性适当的调整间隔,如网络未连接时或应用在后台时重连间隔可以调大一些,网络正常的状态下可以适当调小一些等等,加快重连上的速度。

结尾

最后总结一下,本文在开头将websocket断网重连细分为三个步骤:确定何时需要重连、断开旧连接和发起新连接。然后分别分析了在websocket的不同状态下、不同的网络状态下,如何快速完成这个三个步骤:首先通过定时发送心跳包的方式检测当前连接是否可用,同时监测网络恢复事件,在恢复后立即发送一次心跳,快速感知当前状态,判断是否需要重连;其次正常情况下由服务器断开旧连接,与服务器失去联系时直接弃用旧连接,上层模拟断开,来实现快速断开;最后发起新连接时使用退避算法延迟一段时间再发起连接,同时考虑到资源浪费和重连速度,可以在网络离线时调大重连间隔,在网络正常或网络由offline变为online时缩小重连间隔,使之尽可能快地重连上。

参考:

文章标题:细说 Websocket 快速重连机制,发布者:网易智企,转载请注明出处:https://worktile.com/kb/p/5994

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
网易智企的头像网易智企认证作者
上一篇 2022年3月17日 上午12:33
下一篇 2022年3月17日 上午12:44

相关推荐

  • 大企业oa

    标题:大企业OA系统的关键作用及部署策略 摘要:大型企业面对的管理难题伴随组织规模的增长而日益复杂化。OA(Office Automation)系统成为解决这些问题的有力工具。OA系统主要功能包括:1、内部沟通优化、2、流程自动化、3、文档管理提效、4、数据分析支持决策。其中,流程自动化通过数字化现…

    2024年1月12日
    25600
  • Java中的内部类和匿名类是什么

    内部类(Inner Classes)与匿名类(Anonymous Classes)在Java编程语言中是对象导向性能的特色。内部类 是定义在其他类中的类,有助于逻辑上将类组织在仅使用它的环境中,可以访问外部类的成员,包括私有成员。匿名类 是没有名字的单次使用的内部类,能够快速定义并实例化临时类,用以…

    2024年1月8日
    27300
  • 学习编程梦想是什么

    学习编程的梦想通常涉及创造性地解决问题、开发新技术、改善人类生活质量、实现个人职业发展和经济独立。 其中,创造性地解决问题尤其吸引人。编程提供了一个无限的可能性空间,让人们可以设计和构建各种软件来应对生活中的挑战和问题。这种能力不仅促进了技术的革新,也为程序员提供了巨大的满足感。一旦掌握编程技能,就…

    2024年4月27日
    300
  • 数据库系统与文件系统的根本区别在于什么

    数据库系统与文件系统的根本区别在于:1、数据组织方式;2、数据检索方式;3、数据的完整性和一致性;4、并发处理能力;5、数据安全性。文件系统以文件和文件夹的形式来组织数据。数据库系统使用表格的形式来组织数据。 一、数据组织方式 文件系统:文件系统以文件和文件夹的形式来组织数据。每个文件通常包含特定类…

    2023年7月31日
    1.3K00
  • 国内知名oa系统

    标题:国内知名OA系统 办公自动化系统(OA系统)在提高效率、简化流程方面显著,而国内知名的OA系统包括:1、用友NC系统、2、金蝶K3系统、3、泛微E-office系统、4、致远OA系统。 其中,用友NC系统广泛适用于大型企业与集团,以其强大的集成功能和定制性闻名,通过不断的技术迭代,支持大数据处…

    2024年1月17日
    24200
  • 企业管理人员如何监管项目

    企业管理人员监管项目的方法多种多样,核心策略包括確立明确的项目目标、采用项目管理软件、定期举行项目会议、进行项目风险管理等。其中,采用项目管理软件是科技发展带来的便利,能极大提高项目监管的效率和效果。项目管理软件如Asana、Trello或Jira等,提供任务分配、进度追踪、资源管理、沟通协作等功能…

    2024年4月11日
    5900
  • 项目经理如何做好招标管理

    项目经理在招标管理中的核心职责包括制定招标策略、选择合适的招标方式、确保招标流程的合规性、评估与选择最佳的投标方、以及管理和协调招标过程中的所有活动。具体而言,项目经理需要进行全面的市场调研、编制详实的招标文件、严格控制招标时间表,并保持与所有相关方的沟通,以确保招标过程的透明度和公正性。在招标策略…

    2024年4月11日
    8300
  • oa办公系统到底是什么

    OA办公系统是将计算机、通信等现代化技术运用到传统办公方式,进而形成的一种新型办公方式。办公自动化利用现代化设备和信息化技术,代替办公人员传统的部分手动或重复性业务活动,优质而高效地处理办公事务和业务信息,实现对信息资源的高效利用。 OA办公系统是将计算机、通信等现代化技术运用到传统办公方式,进而形…

    2023年5月28日
    39500
  • 本地oa系统

    标题:本地OA系统的实施与优化策略 摘要:本地OA系统作为提高企业管理效率和工作自动化的重要工具,其成功实施对企业有着举足轻重的作用。本文将全面分析本地OA系统实施的步骤、面临的难题以及解决方案。1、需求分析与定制; 2、系统安装与调试; 3、员工培训与使用; 4、数据安全与备份; 5、持续优化与维…

    2024年1月12日
    22400
  • 甘特图怎么画

    甘特图的画法:1、查看范围基准;2、创建活动;3、对活动进行排序;4、估算资源;5、估计持续时间;6、开发时间表。查看范围基线是指,范围声明、工作分解结构 (WBS) 和 WBS 字典。 1、查看范围基线 召集团队并审查批准的范围基准,该基准由三个部分组成:范围声明、工作分解结构 (WBS) 和WB…

    2023年2月6日
    47200

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部