原文链接:http://www.52im.net/thread-120-1-1.html
本文由微信开发团队人员编写,转自 WeMobileDev,感谢。
一 引言
在2013年11月中旬时,因为基础组件组人手紧张,Leo安排我和春哥去广州轮岗支援。
刚到广州的时候,Ray让我和春哥对Line和WhatsApp的心跳机制进行分析。我和春哥抓包测试了差不多两个多礼拜,在我们基本上摸清了Line和WhatsApp的心跳机制后,Ray才告诉我们真正的任务——对微信的固定心跳进行优化,并告诉我们这不是一件容易的事情。
于是我和春哥开始构思第一个方案,我们开始想用统计的方法来解决问题,当我们拿着第一个方案和Ray讨论时,发现不能优雅应对Ray的所有提问:
- 1、测试环境的准确性,失败到底是因为网络的特性导致还是因为用户当前的环境变化导致的暂时失败。
- 2、临界值界定,如果方案选中的心跳值是临界值,我们该怎么办。
Ray和组件组同事在网络方面有极其丰富的经验,虽然他没有给我们指出明确的方向,但提出的问题帮助我们更快的补齐需要面对的核心问题。这两个问题让我和春哥意识到如果能很好的解决,就可以给出一个比较好的心跳方案。第一个问题我和春哥开始就意识到,第二个问题我们确实在一开始时疏忽了。但直接解决这两个问题确实不容易,这着实让我和春哥迷茫了几天,有两三天在纺园我都没怎么睡着,因为想不到更好的方法。
直到有一天思路发生了一些转变,既然最优解比较复杂,为什么不绕过去,使用有损服务理念找次优解呢。让复杂的事情简单化,好了,想到这里突然有一种拨开云雾的感觉。
二 大体思路
- a)延迟心跳测试法:这是测试结果准确的前提保障,我们认为长连接建立后连续三次成功的短心跳就可以很大程度的保证下一次心跳环境是正常的。
- b)成功一次认定,失败连续累积认定:成功是绝对的,连续失败多次才可能是失败。
- c)临界值避免:我们使用比计算出的心跳稍微小一点的值做为稳定心跳避免临界值。
- d)动态调整:即使在一次完整的智能心跳计算过程中,我们没有找到最好的值,我们还有机会来进行校正。
三 拍板方案
当我和春哥想出第二个简单易行的方案后,我们心里就很有底了,去找Ray讨论,Ray听完后一次通过,然后Ray约了Harvey,给Harvey讲完后,Harvey说听起来可以,可以试试。
然后就开始动手,分析竞品加确定方案花了差不多两个月。写心跳的主要代码,只花了一天时间,我记得那天是年会后的一天。回过头来再看这个方案花费的时间还是值得的,后来灰度的统计数据显示,70%用户都可以达到我们的心跳上限。
搞完智能心跳后一段时间在广州没事干,我就跟Ray商量,Ray让我去测试下WebView的性能瓶颈。然后我跟周斯基一起来做这件事,搞完了安卓客户端WebView性能瓶颈测试后,因为怀孕的老婆一个人在深圳,领导就安排我先回深圳了。春哥坚守着把GCM部分完成后才回深圳。
等我们的心跳版本正式发布后,一年前我在公司km上分享了智能心跳方案,吸引不少做push的同事加入了讨论,感觉这方面的交流还是很有必要的。
四 方案目标
设计此方案的主要目标是,在尽量不影响用户收消息及时性的前提下,根据网络类型自适应的找出保活信令TCP连接的尽可能大的心跳间隔,从而达到减少安卓微信因心跳引起的空中信道资源消耗,减少心跳Server的负载,以及减少部分因心跳引起的耗电。
主要方法是参考WhatsApp和Line中有价值的做法,结合影响TCP连接寿命的因素,实现Android微信后台自适应心跳算法。
* 有关WhatsApp、Lin的消息推送策略请参考文章《 移动端IM实践:WhatsApp、Line、微信的心跳策略分析
》;
* 有关GCM的研究结论请参考文章《 移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信团队)
》。
五 方案需考虑到影响连接寿命的思素
在Android下,不管是GCM,还是微信,都是通过TCP长连接来进行消息收发的,TCP长连接存活,消息收发就及时,所以要对影响TCP连接寿命的因素进行研究。
1、NAT超时
大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断(NAT超时的更多描述见附录9.1)。NAT超时是影响TCP连接寿命的一个重要因素(尤其是国内),所以客户端自动测算NAT超时时间,来动态调整心跳间隔,是一个重要的优化点。
2、DHCP的租期 (lease time)
目前测试发现安卓系统对DHCP的处理有Bug,DHCP租期到了不会主动续约并且会继续使用过期IP,这个问题会造成TCP长连接偶然的断连。(租期问题的具体描述见附录9.2)。
3、网络状态变化
手机网络和WIFI网络切换、网络断开和连上等情况有网络状态的变化,也会使长连接变为无效连接,需要监听响应的网络状态变化事件,重新建立Push长连接。
六 心跳范围选择
1、前后台区分处理:
为了保证微信收消息及时性的体验,当微信处于前台活跃状态时,使用固定心跳。微信进入后台(或者前台关屏)时,先用几次最小心跳维持长链接。然后进入后台自适应心跳计算。这样做的目的是尽量选择用户不活跃的时间段,来减少心跳计算可能产生的消息不及时收取影响。
2、后台自适应心跳选择区间:
可根据自身产品的特点选择合适的心跳范围。
以下是状态转换示意图:
七 自适应心跳算法量化描述
因为每个网络的NAT时间可能不一致。所以需要区分计算,数据网络按subType做关键字,WIFI按WIFI名做关键字。对稳定的网络,因为NAT老化时间的存在,在自适应计算态的时候,暂设计以下步骤在当前心跳区间逼近出最大可用的心跳。
a)变量说明:
- [MinHeart,MaxHeart]——心跳可选区间。
- successHeart——当前成功心跳,初始为MinHeart
- curHeart——当前心跳初始值为successHeart
- heartStep——心跳增加步长
- successStep——稳定期后的探测步长
b)最大值探测步骤(自适应心跳计算流程):
自适应心跳计算流程如上图所示,经过该流程,会找到必然使心跳失败的curHeart(或者MaxHeart),为了保险起见,我们选择比前一个成功值稍微小一点的值作为后台稳定期的心跳间隔。
影响手机网络测试的因素太多,为了尽量保证测试结果的可靠性,我们使用延迟心跳测试法。在我们重新建立TCP连接后,先使用 短心跳连续成功三次,我们才认为网络相对稳定,可以使用curHeart进行一次心跳测试。图4-2显示了一次有效心跳测试过程。图4-3显示了在没有达到稳定网络环境时,我们会一直使用固定短心跳直到满足三次连续短心跳成功。
使用延迟心跳测试的好处是,可以剔除偶然失败,和网络变化较大的情况(如地铁),使测试结果相对可靠(五次延迟测试确定结论)。同时在网络波动较大的情况,使用短心跳,保证收取消息相对及时。
c)运行时的动态调整策略(已经按测算心跳稳定值后)
NAT超时值算出来后,在维持心跳的过程中的策略。
- 无网络、网络时好时坏、偶然失败、NAT超时变小:
在后台稳定期发生心跳发生失败后,我们使用延迟心跳测试法测试五次。如果有一次成功,则保持当前心跳值不变;如果五次测试全失败,重新计算合理心跳值。该过程如图4-4所示,有一点需要注意,每个新建的长连接需要先用短心跳成功维持3次后才用successHeart进行心跳。后台稳定态动态调整心跳策略如下图:
- NAT超时变大:
以周为周期,每周三将后台稳定态调至自适应计算态,使用心跳延迟法往后探测心跳间隔。
- successHeart是NAT超时临界值:
因为我们现在选择的是一个比successHeart稍小的值作为稳定值,所以在计算过程中可以避开临界值。当运营商在我们后台稳定期将NAT超时调整为我们当前计算值,那么由于我们每周会去向下探索,所以下一周探测时也可以及时调整正确。
d)冗余Sync和心跳
在用户的一些主动操作以及联网状态改变时,增加冗余Sync和心跳,确保及时收到消息。
- 1、当用户点亮屏幕的时候,做一次心跳。
- 2、当微信切换到前台时,做一次Sync。
- 3、联网时重建信令TCP,做一次Sync。
八 可能存在的风险及预防措施
DHCP租期因素:
- 1、问题:根据目前的测试结果显示,安卓不续约到期的IP Bug,会导致TCP连接在不确定的时间点失效,从而会导致一次心跳失败。
- 2、预防:统计后台稳定期的心跳成功率,上报给后台。后台可以按地区分网络监控这个指标的波动,并且后台可以根据不同的波动,动态调整某区域特定网络下可选的心跳区间。
9 附录
1附录A:NAT超时介绍
因为 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要连接 Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯。
大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断。
下表列出一些已测试过的网络的NAT超时时间 (更多数据由于测试条件所限没有测到):
地区/网络 |
NAT超时时间 |
中国移动3G和2G |
5分钟 |
中国联通2G |
5分钟 |
中国电信3G |
大于28分钟 |
美国3G |
大于28分钟 |
台湾3G |
大于28分钟 |
长连接心跳间隔必须要小于NAT超时时间(aging-time),如果超过aging-time不做心跳,TCP长连接链路就会中断,Server就无法发送Push给手机,只能等到客户端下次心跳失败后,重建连接才能取到消息。
2附录B:安卓DHCP的租期(lease time)问题
目前测试发现安卓系统对DHCP的处理有Bug:
- 1、DHCP租期到了不会主动续约并且会继续使用过期IP:
详细描述见 http://www.net.princeton.edu/android/android-stops-renewing-lease-keeps-using-IP-address-11236.html。这个问题导致的问题表象是,在超过租期的某个时间点(没有规律)会导致IP过期,老的TCP连接不能正常收发数据。并且系统没有网络变化事件,只有等应用判断主动建立新的TCP连接才引起安卓设备重新向DHCP Server申请IP租用。
- 2、未到租期的一半时间,安卓设备重新向DHCP Server申请IP租用。从目前测试结果来看,这种现象恢复的比较快。
- 3、移动2G/3G,联通2G没有抓到DHCP。
- 4、美国3G下抓取24小时,没有抓到DHCP。
全站即时通讯技术资料分类
[1] 网络编程基础资料:
《 TCP/IP详解
- 第11章·UDP:用户数据报协议
》
《 TCP/IP详解
- 第17章·TCP:传输控制协议
》
《 TCP/IP详解
- 第18章·TCP连接的建立与终止
》
《 TCP/IP详解
- 第21章·TCP的超时与重传
》
《 理论经典:TCP协议的3次握手与4次挥手过程详解
》
《 理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程
》
《 计算机网络通讯协议关系图(中文珍藏版)
》
《 NAT详解:基本原理、穿越技术(P2P打洞)、端口老化等
》
《 UDP中一个包的大小最大能多大?
》
《 Java新一代网络编程模型AIO原理及Linux系统AIO介绍
》
《 NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战
》
《 NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
》
>> 更多同类文章 ……
[2] 有关IM/推送的通信格式、协议的选择:
《 为什么QQ用的是UDP协议而不是TCP协议?
》
《 移动端即时通讯协议选择:UDP还是TCP?
》
《 如何选择即时通讯应用的数据传输格式
》
《 强列建议将Protobuf作为你的即时通讯应用数据传输格式
》
《 移动端IM开发需要面对的技术问题(含通信协议选择)
》
《 简述移动端IM开发的那些坑:架构设计、通信协议和客户端
》
《 理论联系实际:一套典型的IM通信协议设计详解
》
《 58到家实时消息系统的协议设计等技术实践分享
》
>> 更多同类文章 ……
[3] 有关IM/推送的心跳保活处理:
《 Android进程保活详解:一篇文章解决你的所有疑问
》
《 Android端消息推送总结:实现原理、心跳保活、遇到的问题等
》
《 为何基于TCP协议的移动端IM仍然需要心跳保活机制?
》
《 微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
》
《 微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
》
《 移动端IM实践:实现Android版微信的智能心跳机制
》
《 移动端IM实践:WhatsApp、Line、微信的心跳策略分析
》
>> 更多同类文章 ……
[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.264、V8的前世今生
》
《 简述开源实时音视频技术WebRTC的优缺点
》
《 良心分享:WebRTC 零基础开发者教程(中文)
》
>> 更多同类文章 ……
[8] IM开发综合文章:
《 移动端IM开发需要面对的技术问题
》
《 开发IM是自己设计协议用字节流好还是字符流好?
》
《 请问有人知道语音留言聊天的主流实现方式吗?
》
《 IM系统中如何保证消息的可靠投递(即QoS机制)
》
《 谈谈移动端 IM 开发中登录请求的优化
》
《 完全自已开发的IM该如何设计“失败重试”机制?
》
《 微信对网络影响的技术试验及分析(论文全文)
》
《 即时通讯系统的原理、技术和应用(技术论文)
》
《 开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀
》
>> 更多同类文章 ……
[9] 开源移动端IM技术框架资料:
《 开源移动端IM技术框架MobileIMSDK:快速入门
》
《 开源移动端IM技术框架MobileIMSDK:常见问题解答
》
《 开源移动端IM技术框架MobileIMSDK:压力测试报告
》
《 开源移动端IM技术框架MobileIMSDK:Android版Demo使用帮助
》
《 开源移动端IM技术框架MobileIMSDK:Java版Demo使用帮助
》
《 开源移动端IM技术框架MobileIMSDK:iOS版Demo使用帮助
》
《 开源移动端IM技术框架MobileIMSDK:Android客户端开发指南
》
《 开源移动端IM技术框架MobileIMSDK:Java客户端开发指南
》
《 开源移动端IM技术框架MobileIMSDK:iOS客户端开发指南
》
《 开源移动端IM技术框架MobileIMSDK:Server端开发指南
》
>> 更多同类文章 ……
[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
附录:有关QQ、微信的文章汇总
[1] 有关QQ、微信的技术文章:
《 微信后台团队:微信后台异步消息队列的优化升级实践分享
》
《 微信团队原创分享:微信客户端SQLite数据库损坏修复实践
》
《 腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率
》
《 腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)
》
《 腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)
》
《 微信Mars:微信内部正在使用的网络层封装库,即将开源
》
《 如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
》
《 开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]
》
《 微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
》
《 微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
》
《 微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
》
《 Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]
》
《 微信团队原创分享:Android版微信从300KB到30MB的技术演进
》
《 微信技术总监谈架构:微信之道——大道至简(演讲全文)
》
《 微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]
》
《 如何解读《微信技术总监谈架构:微信之道——大道至简》
》
《 微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]
》
《 微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案
》
《 微信朋友圈海量技术之道PPT [附件下载]
》
《 微信对网络影响的技术试验及分析(论文全文)
》
《 一份微信后台技术架构的总结性笔记
》
《 架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]
》
《 快速裂变:见证微信强大后台架构从0到1的演进历程(一)
》
《 快速裂变:见证微信强大后台架构从0到1的演进历程(二)
》
《 微信团队原创分享:Android内存泄漏监控和优化技巧总结
》
《 全面总结iOS版微信升级iOS9遇到的各种“坑”
》
《 微信团队原创资源混淆工具:让你的APK立减1M
》
《 微信团队原创Android资源混淆工具:AndResGuard [有源码]
》
《 Android版微信安装包“减肥”实战记录
》
《 iOS版微信安装包“减肥”实战记录
》
《 移动端IM实践:iOS版微信界面卡顿监测方案
》
《 微信“红包照片”背后的技术难题
》
《 移动端IM实践:iOS版微信小视频功能技术方案实录
》
《 移动端IM实践:Android版微信如何大幅提升交互性能(一)
》
《 移动端IM实践:Android版微信如何大幅提升交互性能(二)
》
《 移动端IM实践:实现Android版微信的智能心跳机制
》
《 移动端IM实践:WhatsApp、Line、微信的心跳策略分析
》
《 移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
》
《 移动端IM实践:iOS版微信的多设备字体适配方案探讨
》
>> 更多同类文章 ……
[2] 有关QQ、微信的技术故事:
《 技术往事:创业初期的腾讯——16年前的冬天,谁动了马化腾的代码
》
《 技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史
》
《 开发往事:深度讲述2010到2015,微信一路风雨的背后
》
《 开发往事:微信千年不变的那张闪屏图片的由来
》
《 开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)
》
《 一个微信实习生自述:我眼中的微信开发团队
》
>> 更多同类文章 ……