假设有以下突发意外情况:

  • 用户进入信号不好的地方,手机没有网络信号了
  • 上网的路由器突然掉线了
    这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号……
    上面情况都会导致“长连接”不可用。

我们知道,为了让消息能更加实时、可靠、快速地触达到接收方,大部分 IM 系统会通过“长连接”的方式来建立收发双方的通信通道,长连接一旦建立,就一直存在,除非网络被中断。

有了这基于 TCP 长连接的通信协议,在用户上线连接时,可以在服务端维护好连接到服务器的用户设备和具体 TCP 连接的映射关系,服务端也能通过这个映射关系随时找到对应在线的用户的客户端。对于发送方来说,发送消息也能通过“长连接”通道把消息给到 IM 服务端。

一、什么是心跳机制

但长连接并不是永久可用的,当长连接在中间链路出问题时,为了不使用户感知到,应快速通知连接的两端,并重新建立新的可用连接,从而使长连接一直保持“高可用”状态,这个能够快速、不间断识别连接可用性的机制,称为“心跳机制”。

“心跳机制”会持续地往连接发送“模拟数据”,一方面是为了试探连接的可用性,另一方面也是为了保证数据的持续流通,让连接在没有真正业务数据收发的情况下,不会被中间的网络运营商以为连接没有被使用而切断连接。

二、心跳机制的优点

1. 降低服务端开销

消息之所以能够实现“服务端推送”,是因为针对每一台上线的设备,都会在 IM 服务端维护相应的 用户设备<->网络连接 这样的映射关系,除此之外,为了节省网络开销,还会在服务端临时缓存一些不用每次请求都携带的客户端信息,如 app 版本号、操作系统、网络状态等,甚至还会在服务端维护一些“用户在线状态”和“所有在线设备”这些信息,便于业务使用,这样客户端一旦建好长连接,只需要首次携带这些信息,后续请求可以不用再携带,而是使用 IM 服务端缓存的这些信息。

若没有心跳机制,当长连接异常而 IM 服务端无法感知到,会产生两种不良后果:

  • 无效的长连接一直在被维护,不管是连接句柄,还是缓存大量“映射关系”、“设备状态”等信息,都会导致资源浪费;
  • 向无效连接推送消息,以及后续的重试推送,都会降低服务的整体性能。
2. 支持客户端断线重连

当客户端和 IM 服务端之间的网络在中间某些环节断开,或服务器负载过高,则会出现客户端在一定的超时时间内,发出的心跳包得不到 IM 服务端响应的现象,这时客户端就可以认为和服务端的长连接不可用,自动断线重连,保持长连接的可用性。

3. 连接保活

即使用户网络和中间路由网络都正常,若一直没有数据收发,运营商就会将这个长连接清除掉,来降低自身网关的压力,这个清除动作不会被客户端和 IM 服务端感知到,为了避免被运营商干掉,客户端会在没有消息收发的空闲时间给服务端发送心跳包,使长连接存活时间更长。

三、心跳检测的方式

1. TCP Keepalive

Keepalive 并不是 TCP 协议的一部分,但大多数操作系统都实现了这个机制,操作系统默认是关闭这个特性的,需要由应用层来开启。TCP 的 keepalive 会在连接空闲期按一定的频次,自动发送不携带数据的探测报文,来探测对方是否存活。

Keepalive 默认是关闭的,开启 Keepalive 需要在 TCP 的 socket 中单独开启,操作系统层面有三个参数影响到 Keepalive 的行为:

tcp_keepalive_time 7200 // 心跳周期:距离上次传送数据多少时间未收到新报文判断为开始检测,单位秒,默认7200s
tcp_keepalive_intvl 75  // 超时时间:检测开始每多少时间发送心跳包,单位秒,默认75s
tcp_keepalive_probes 9  // 失败后重试次数:发送几次心跳包对方未响应则close连接,默认9次

优点:

  • 易用性好:作为系统层 TCP/IP 协议层的已有实现,不需要其他开发工作量,上层应用只需要处理探测后的连接异常情况即可。
  • 网络消耗小:心跳包不携带数据,带宽资源浪费少。

缺点:

  • 心跳间隔灵活性差:一台服务器某一时间只能调整为固定间隔的心跳。
  • 结果反映差:可以探测网络连接层的存活,但并不代表真正的应用层处于可用状态,即网络仍然是通的,但应用已不可用。
2. 应用层心跳

应用层心跳实际上是客户端每隔一定时间间隔,向 IM 服务端发送一个业务层的数据包告知自身存活。如果 IM 服务端在一定时间内没有收到心跳包,就认定客户端由于某种原因连接不可达了,此时就会从 IM 服务端把这个连接断开,同时清除相应分配的其他资源。
优点:

  • 心跳间隔灵活性强:应用层心跳可以根据实际网络的情况,来灵活设置心跳间隔,节省网络流量。
  • 结果反馈准:由于需要在应用层进行发送和接收的处理,不仅能代表网络可用,更能反映应用的可用性。

缺点:

  • 额外的数据传输开销(非常小)。
  • 实现逻辑根据心跳策略而定,有的实现起来略复杂。
3. 智能心跳

心跳间隔能够根据网络环境自动调整,逐步逼近 NAT 超时临界点,在保证 NAT 不超时的情况下尽量节约设备资源,常见的有二分法。但需要权衡使用。

四、小结

  • 能够快速、不间断识别连接可用性的机制,称为“心跳机制”。
  • 心跳机制可以降低服务端连接维护无效连接的开销,支持客户端快速识别无效连接、自动断线重连,连接保活,避免被运营商 NAT 超时断开。
  • 心跳可以使用 TCP Keepalive、应用层心跳等方式来检测,前者可探测网络连接可用性,后者可探测网络和服务的可用性。

版权声明:本文为sunshineliulu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/sunshineliulu/p/12245975.html