为何说基于TCP的移动端IM仍然须要心跳保活?

一、前言

不少人认为,TCP协议自身先天就有KeepAlive机制,为什么基于它的通信连接,仍然须要在应用层实现额外的心跳保活?本文将从移动端IM实践的角度告诉你,即便使用的是TCP协议,应用层的心跳保活仍旧必不可少。

有关TCP协议的权威理论介绍,请参见《TCP/IP详解》这本书。php

说明:本文引用了网易云信项望烽的技术文章,感谢分享。 (本文同步发布于:http://www.52im.net/thread-33-1-1.htmlhtml

二、学习交流 

- 即时通信开发交流群: 215891622 [推荐]android

- 移动端IM开发推荐文章:《新手入门一篇就够:从零开发移动端IM算法

三、参考资料

TCP/IP详解 - 第11章·UDP:用户数据报协议
TCP/IP详解 - 第17章·TCP:传输控制协议
TCP/IP详解 - 第18章·TCP链接的创建与终止
TCP/IP详解 - 第21章·TCP的超时与重传
通俗易懂-深刻理解TCP协议(上):理论基础
通俗易懂-深刻理解TCP协议(下):RTT、滑动窗口、拥塞处理
理论经典:TCP协议的3次握手与4次挥手过程详解
计算机网络通信协议关系图(中文珍藏版)
NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等编程

四、本文源起

作移动端IM多年以来,常常会与相关人员进行讨论和交流。也常常会碰到些较真的技术人员询问技术细节,如主流的移动端IM如何作心跳、如何保证消息必达、如何加快文件上传等。由于平时工做太忙,没有时间深刻整理和总结,每每只能简略介绍,并不能具体展开,因而决定写成文字,也有了有关移动 IM 问题处理的系列文章。安全

五、什么是心跳保活?


为何说基于TCP的移动端IM仍然须要心跳保活?_a.jpg 

在使用 TCP 长链接的 IM 服务设计中,每每都会涉及到心跳。心跳通常是指某端(绝大多数状况下是客户端)每隔必定时间向对端发送自定义指令,以判断双方是否存活,因其按照必定间隔发送,相似于心跳,故被称为心跳指令。

有兴趣了解IM/推送的心跳保活技术的文章,请参见:

Android进程保活详解:一篇文章解决你的全部疑问
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
>> 更多同类文章 ……服务器

六、TCP协议不是自带KeepAlive的吗?

那么问题就随之而来了:为何须要在应用层作心跳,难道 TCP 不是个可靠链接吗?咱们不可以依赖 TCP 作断线检测吗?好比使用 TCP 的 KeepAlive 机制来实现。应用层心跳是目前的最佳实践吗?怎么样的心跳才是最佳实践。

不少作移动端IM的同行,之前确实没有仔细考虑过这些问题,潜意识里想固然的认为这仅仅只是个简单的心跳而已啊。好吧,事实并不是这么简单,请继续往下看。微信

七、IM中保持有效长链接的重要性

对于客户端而言,使用 TCP 长链接来实现业务的最大驱动力在于:在当前链接可用的状况下,每一次请求都只是简单的数据发送和接受,免去了 DNS 解析,链接创建等时间,大大加快了请求的速度,同时也有利于接受服务器的实时消息。但前提是链接可用。

若是链接没法很好地保持,每次请求就会变成撞大运:运气好,经过长链接发送请求并收到反馈。运气差,当前链接已失效,请求迟迟没有收到反馈直到超时,又须要一次链接创建的过程,其效率甚至还不如 HTTP。而链接保持的前提必然是检测链接的可用性,并在链接不可用时主动放弃当前链接并创建新的链接。

基于这个前提,必需要有一种机制用于检测链接可用性。同时移动网络的特殊性也要求客户端须要在空余时间发送必定的信令,避免链接被回收。详见微信和运营商的撕B(另外一篇针对微信的信令风暴技术研究文章请见:微信对网络影响的技术试验及分析

而对于服务器而言,可以及时获悉链接可用性也很是重要:一方面服务器须要及时清理无效链接以减轻负载,另外一方面也是业务的需求,如游戏副本中服务器须要及时处理玩家掉线带来的问题。网络

八、TCP的KeepAlive没法替代应用层心跳保活机制的缘由

上面说了保持链接的重要性,那么如今回到具体实现上。为何咱们须要使用应用层心跳来作检测,而不是直接使用 TCP 的特性呢?

咱们知道 TCP 是一个基于链接的协议,其链接状态是由一个状态机进行维护,链接完毕后,双方都会处于 established 状态,这以后的状态并不会主动进行变化。这意味着若是上层不进行任何调用,一直使 TCP 链接空闲,那么这个链接虽然没有任何数据,但还是保持链接状态,一天、一星期、甚至一个月,即便在这期间中间路由崩溃重启无数次。举个现实中常常遇到的栗子:当咱们 ssh 到本身的 VPS 上,而后不当心踢掉网线,此时的网络变化并不会被 TCP 检测出,当咱们从新插回网线,仍旧能够正常使用 ssh,同时此时并无发生任何 TCP 的重连。

有人会说 TCP 不是有 KeepAlive 机制么,经过这个机制来实现不就能够了吗?可是事实上,TCP KeepAlive 的机制其实并不适用于此。Keep Alive 机制开启后,TCP 层将在定时时间到后发送相应的 KeepAlive 探针以肯定链接可用性。通常时间为 7200 s(详情请参见《TCP/IP详解》中第23章),失败后重试 10 次,每次超时时间 75 s。显然默认值没法知足咱们的需求,而修改过设置后就能够知足了吗?答案仍旧是否认的。

由于 TCP KeepAlive 是用于检测链接的死活,而心跳机制则附带一个额外的功能:检测通信双方的存活状态。二者听起来彷佛是一个意思,但实际上却截然不同。

考虑一种状况,某台服务器由于某些缘由致使负载超高,CPU 100%,没法响应任何业务请求,可是使用 TCP 探针则仍旧可以肯定链接状态,这就是典型的链接活着但业务提供方已死的状态,对客户端而言,这时的最好选择就是断线后从新链接其余服务器,而不是一直认为当前服务器是可用状态,一直向当前服务器发送些必然会失败的请求。

从上面咱们能够知道,KeepAlive 并不适用于检测双方存活的场景,这种场景还得依赖于应用层的心跳。应用层心跳有着更大的灵活性,能够控制检测时机,间隔和处理流程,甚至能够在心跳包上附带额外信息。从这个角度而言,应用层的心跳的确是最佳实践。架构

九、心跳保活机制的实现方案参考

从上面咱们能够得出结论,目前而言,应用层心跳的确是检测链接有效性,双方是否存活的最佳实践,那么剩下的问题就是怎么实现。

最简单粗暴作法固然是定时心跳,如每隔 30 秒心跳一次,15 秒内没有收到心跳回包则认为当前链接已失效,断开链接并进行重连。这种作法最直接,实现也简单。惟一的问题是比较耗电和耗流量。以一个协议包 5 个字节计算,一天收发 2880 个心跳包,一个月就是 5 * 2 * 2880 * 30 = 0.8 M 的流量,若是手机上多装几个 IM 软件,每月光心跳就好几兆流量没了,更不用说频繁的心跳带来的电量损耗。

既然频繁心跳会带来耗电和耗流量的弊端,改进的方向天然是减小心跳频率,但也不能过于影响链接检测的实时性。基于这个需求,通常能够将心跳间隔根据程序状态进行调整,当程序在后台时(这里主要考虑安卓),尽可能拉长心跳间隔,5 分钟、甚至 10 分钟均可以。

而当 App 在前台时则按照原来规则操做。链接可靠性的判断也能够放宽,避免一次心跳超时就认为链接无效的状况,使用错误积累,只在心跳超时 n 次后才断定当前链接不可用。固然还有一些小 trick 好比从收到的最后一个指令包进行心跳包周期计时而不是固定时间,这样也可以必定程度减小心跳次数。

(本文同步发布于:http://www.52im.net/thread-33-1-1.html

 

附录:更多IM技术文章

[1] 更多网络编程基础资料:
理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程
UDP中一个包的大小最大能多大?
Java新一代网络编程模型AIO原理及Linux系统AIO介绍
NIO框架入门(三):iOS与MINA二、Netty4的跨平台UDP双向通讯实战
NIO框架入门(四):Android与MINA二、Netty4的跨平台UDP双向通讯实战
>> 更多同类文章 ……

[2] 有关IM/推送的通讯格式、协议的选择:
为何QQ用的是UDP协议而不是TCP协议?
移动端即时通信协议选择:UDP仍是TCP?
如何选择即时通信应用的数据传输格式
强列建议将Protobuf做为你的即时通信应用数据传输格式
移动端IM开发须要面对的技术问题(含通讯协议选择)
简述移动端IM开发的那些坑:架构设计、通讯协议和客户端
理论联系实际:一套典型的IM通讯协议设计详解
58到家实时消息系统的协议设计等技术实践分享
>> 更多同类文章 ……

[4] 有关WEB端即时通信开发:
新手入门贴:史上最全Web端即时通信技术原理详解
Web端即时通信技术盘点:短轮询、Comet、Websocket、SSE
SSE技术详解:一种全新的HTML5服务器推送事件技术
Comet技术详解:基于HTTP长链接的Web端实时通讯技术
WebSocket详解(一):初步认识WebSocket技术
socket.io实现消息推送的一点实践及思路
>> 更多同类文章 ……

[5] 有关IM架构设计:
浅谈IM系统的架构设计
简述移动端IM开发的那些坑:架构设计、通讯协议和客户端
一套原创分布式即时通信(IM)系统理论架构方案
从零到卓越:京东客服即时通信系统的技术架构演进历程
蘑菇街即时通信/IM服务器开发之架构选择
腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT
微信技术总监谈架构:微信之道——大道至简(演讲全文)
如何解读《微信技术总监谈架构:微信之道——大道至简》
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
17年的实践:腾讯海量产品的技术方法论
>> 更多同类文章 ……

[6] 有关IM安全的文章:
即时通信安全篇(一):正确地理解和使用Android端加密算法
即时通信安全篇(二):探讨组合加密算法在IM中的应用
即时通信安全篇(三):经常使用加解密算法与通信安全讲解
即时通信安全篇(四):实例分析Android中密钥硬编码的风险
传输层安全协议SSL/TLS的Java平台实现简介和Demo演示
理论联系实际:一套典型的IM通讯协议设计详解(含安全层设计)
微信新一代通讯安全解决方案:基于TLS1.3的MMTLS详解
来自阿里OpenIM:打造安全可靠即时通信服务的技术实践分享
>> 更多同类文章 ……

[7] 有关实时音视频开发:
即时通信音视频开发(一):视频编解码之理论概述
即时通信音视频开发(二):视频编解码之数字视频介绍
即时通信音视频开发(三):视频编解码之编码基础
即时通信音视频开发(四):视频编解码之预测技术介绍
即时通信音视频开发(五):认识主流视频编码技术H.264
即时通信音视频开发(六):如何开始音频编解码技术的学习
即时通信音视频开发(七):音频基础及编码原理入门
即时通信音视频开发(八):常见的实时语音通信编码标准
即时通信音视频开发(九):实时语音通信的回音及回音消除概述
即时通信音视频开发(十):实时语音通信的回音消除技术详解
即时通信音视频开发(十一):实时语音通信丢包补偿技术详解
即时通信音视频开发(十二):多人实时音视频聊天架构探讨
即时通信音视频开发(十三):实时视频编码H.264的特色与优点
即时通信音视频开发(十四):实时音视频数据传输协议介绍
即时通信音视频开发(十五):聊聊P2P与实时音视频的应用状况
即时通信音视频开发(十六):移动端实时音视频开发的几个建议
即时通信音视频开发(十七):视频编码H.26四、V8的前世此生
简述开源实时音视频技术WebRTC的优缺点
良心分享:WebRTC 零基础开发者教程(中文)
>> 更多同类文章 ……

[8] IM开发综合文章:
移动端IM开发须要面对的技术问题
开发IM是本身设计协议用字节流好仍是字符流好?
请问有人知道语音留言聊天的主流实现方式吗?
IM系统中如何保证消息的可靠投递(即QoS机制)
谈谈移动端 IM 开发中登陆请求的优化
彻底自已开发的IM该如何设计“失败重试”机制?
微信对网络影响的技术试验及分析(论文全文)
即时通信系统的原理、技术和应用(技术论文)
开源IM工程“蘑菇街TeamTalk”的现状:一场虎头蛇尾的开源秀
>> 更多同类文章 …… 

[9] 开源移动端IM技术框架资料:
开源移动端IM技术框架MobileIMSDK:快速入门
开源移动端IM技术框架MobileIMSDK:常见问题解答
开源移动端IM技术框架MobileIMSDK:压力测试报告
>> 更多同类文章 ……

[10] 有关推送技术的文章:
iOS的推送服务APNs详解:设计思路、技术原理及缺陷等
Android端消息推送总结:实现原理、心跳保活、遇到的问题等
扫盲贴:认识MQTT通讯协议
一个基于MQTT通讯协议的完整Android推送Demo
求教android消息推送:GCM、XMPP、MQTT三种方案的优劣
移动端实时消息推送技术浅析
扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别
绝对干货:基于Netty实现海量接入的推送服务技术要点
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
为什么微信、QQ这样的IM工具不使用GCM服务推送消息?
>> 更多同类文章 ……

[11] 更多即时通信技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

相关文章
相关标签/搜索