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

  • 用户进入信号不好的地方,手机没有网络信号了
  • 上网的路由器突然掉线了

    这个时候,比如微信发消息,消息就会转圈圈,甚至变成红色叹号……

    上面情况都会导致“长连接”不可用。

我们知道,为了让消息能更加实时、可靠、快速地触达到接收方,大部分 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、应用层心跳等方式来检测,前者可探测网络连接可用性,后者可探测网络和服务的可用性。

《即时消息技术剖析与实战》学习笔记8——IM系统如何保证长连接的可用性:心跳机制的更多相关文章

  1. 《即时消息技术剖析与实战》学习笔记4——IM系统如何保证消息的可靠性

    IM 系统中,保证消息的可靠投递主要体现在两方面,一是消息的不丢失,二是消息的不重复. 一.消息不丢失 消息丢失的原因 首先看一下发送消息的流程,如下图所示: 消息.可以采取"时间戳比对&q ...

  2. 《即时消息技术剖析与实战》学习笔记5——IM系统如何保证消息的一致性

    一.什么是消息一致性 消息一致性指的是消息的时序一致性,即消息收发的一致性.如果不能保证时序一致性,就会造成聊天语义不连贯,引起误会. 对于点对点的聊天场景,时序一致性保证接收方的接收顺序和发送方的发 ...

  3. 《即时消息技术剖析与实战》学习笔记1——IM系统的架构

    一.IM的应用场景 聊天.直播.在线客服.物联网等所有需要实时互动.高实时性的场景,都需要应用到 IM 技术.

  4. 《即时消息技术剖析与实战》学习笔记10——IM系统如何应对高并发

    一.IM 系统的高并发场景 IM 系统中,高并发多见于直播互动场景.比如直播间,在直播过程中,观众会给主播打赏.送礼.发送弹幕等,尤其是明星直播间,几十万.上百万人的规模一点也不稀奇.近期随着武汉新型 ...

  5. 《即时消息技术剖析与实战》学习笔记6——IM系统如何保证消息的安全性

    在消息产生.流转的各个环节中,需要保证消息传输安全性.消息存储安全性.消息内容安全性. 一.消息传输安全性 消息传输的重要防范点有两个,一是访问入口安全,二是传输链路安全. 1.HttpDNS保证访问 ...

  6. 《即时消息技术剖析与实战》学习笔记12——IM系统如何提升图片、音视频消息发送、浏览的体验

    IM系统如何提升用户发送.浏览图片和音视频消息的体验呢?一是保证图片.音视频消息发送得又快又稳,二是保证用户浏览播放图片.音视频消息时流畅不卡顿. 一.提升用户发送图片.音视频的体验 1. 多上传接入 ...

  7. 《即时消息技术剖析与实战》学习笔记3——IM系统如何保证消息的实时性

    IM 技术经历过几次迭代升级,如图所示: 从简单.低效的短轮询逐步升级到相对效率可控的长轮询: 全双工的 Websocket 彻底解决了服务端的推送问题: 基于 TCP 长连接衍生的 IM 协议,能够 ...

  8. 《即时消息技术剖析与实战》学习笔记11——IM系统如何保证服务高可用:流量控制和熔断机制

    IM 系统的不可用主要有以下两个原因: 一是无法预测突发流量,即使进行了服务拆分.自动扩容,但流量增长过快时,服务已经不可用了: 二是业务中依赖的这些接口.资源不可用或变慢时,比如发消息可能需要依赖& ...

  9. 《即时消息技术剖析与实战》学习笔记7——IM系统的消息未读

    一.什么是消息未读 消息未读包括会话未读和总未读.前者指的是当前用户和某一聊天方的未读消息数,后者指的是当前用户的所有未读消息数,也就是所有会话未读的和.比如用户A收到用户B的2条消息,还收到用户C的 ...

随机推荐

  1. sql临时表与变量表

    1)临时表存储在 tempdb 中,当不再使用时会自动删除 一般使用如下: --创建临时表 select * into #temp from TABLE --使用临时表 select * from # ...

  2. 机器学习——Bagging与随机森林算法及其变种

    Bagging算法:  凡解:给定M个数据集,有放回的随机抽取M个数据,假设如此抽取3组,3组数据一定是有重复的,所以先去重.去重后得到3组数据,每组数据量分别是s1,s2,s3,然后三组分别训练组合 ...

  3. Linux忘记root密码后如何在grub界面中以单用户模式进入系统并重置密码的方法

    本文将介绍在Linux系统中忘记root用户密码的情况下,如何在gurb界面进入单用户模式并重置root用户密码.在单用户模式下,用户不需要输入任何密码即可进入系统并可以修改密码.实验步骤如下: 1. ...

  4. 解决echarts中的点击事件点击后走多次接口

    使用echarts图点击图之后,走了很多次接口,后来发现添加一个off事件就可以解决了,具体如下:

  5. 【题解】HDU4689 Derangement(有技巧的计数DP)

    [题解]HDU4689 Derangement(有技巧的计数DP) 传送门 呵呵没告诉我多测组数,然后\(n\le 20,7000\mathrm{ms}\)我写了个状压上去T了 题目大意: 要你求错排 ...

  6. 「CH2401」送礼物 解题报告

    CH2401 送礼物 描述 作为惩罚,GY被遣送去帮助某神牛给女生送礼物(GY:貌似是个好差事)但是在GY看到礼物之后,他就不这么认为了.某神牛有N个礼物,且异常沉重,但是GY的力气也异常的大(-_- ...

  7. c语言中自定义bool类型模板

    首先,c语言中没有bool类型,只有c++中有,所以需要自定义,即c中表示bool类型的方法: 1.模板1 typedef int bool; #define false 0 #define true ...

  8. 关于MySQL幻读的实验

    该实验基于 CentOS 7 + MySQL 5.7 进行 打开两个窗口连接到MySQL 第一个连接的事务我们命名为  T1 第二个连接的事务我们命名为 T2 T2 发生在 T1 的 O1 操作结束以 ...

  9. cassandra中的ACID,与RDBMS中的事务有何不同?

    Cassandra中的ACID标准 Apache Cassandra不遵循具有回滚或锁定机制的ACID(原子性,一致性,隔离性,持久性)事务,而是提供原子,隔离和持久的事务,并具有最终和可调的一致性, ...

  10. 基于JGraphT实现的路径探寻

    基于JGraphT实现的路径探寻 业务中提出基于内存,探寻的两点间的有向以及无向路径,多点间的最小子图等需求,以下记录使用JGraphT的实现过程. GraphT是免费的Java类库,提供数学图论对象 ...