其他分享
首页 > 其他分享> > 【转载】Android微信智能心跳方案

【转载】Android微信智能心跳方案

作者:互联网

PS: 原文链接为: 【Android微信智能心跳方案】,作者为 微信团队的 phoenix
这里转载,主要是为了学习这个智能心跳方案,并实践之。

前言:在13年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的同事加入了讨论,感觉这方面的交流还是很有必要的。

好了,废话了很多,下面分享一下微信的智能心跳方案细节。由于字数比较多,建议大家使用PC版微信查看。

1、主要目标

本方案的主要目标是,在尽量不影响用户收消息及时性的前提下,根据网络类型自适应的找出保活信令TCP连接的尽可能大的心跳间隔,从而达到减少安卓微信因心跳引起的空中信道资源消耗,减少心跳Server的负载,以及减少部分因心跳引起的耗电。

主要方法是参考WhatsApp和Line中有价值的做法,结合影响TCP连接寿命的因素,实现Android微信后台自适应心跳算法,同时使用GCM作为辅助通道增加新消息通知的可靠性。

2. WhatsApp、Line、微信的Push策略分析

2.1 WhatsApp

在不支持GCM的设备上,采用和微信类似的长连接+心跳策略,WIFI和手机网络下的心跳间隔都为4分45秒,心跳5次后,主动断开连接再重连。

在支持GCM的设备上,主要靠GCM来激活WhatsApp,WhatsApp启动后,会建立一个与服务器的长连接,直接通过此长连接发送Push消息,这个长连接10分钟无消息就会主动断掉,且这十分钟内不做心跳,断掉后WhatsApp客户端和它的服务器不再有连接。当有消息时候,服务器发现没有长连接会发送GCM消息,手机收到GCM消息后,会重新建立长连接来收取消息,10分钟无消息会再断开,如此循环。

2.2 Line

从测试中发现Line在国内、台湾、美国使用了不同的策略。

1、美国(使用GCM):

启动时,会保持7分钟心跳(CDMA2000网络)维持长连接半小时,之后主动断开长连接。当有消息时,服务器会发送GCM消息,Line客户端接收到GCM消息后,重新建立长连接,并再次用心跳维持半个小时。

2、国内(不使用GCM):

在国内,同样帐号在相同网络,不同的手机上测出了两种策略:

图片

图2-1 Line在国内的轮询策略

3、台湾(不使用GCM):

从IBG同事win和guang提供的测试数据中看到,台湾使用的策略跟国内的轮询策略类似。

2.3 微信

微信没有使用GCM,自己维护TCP长连接,使用固定心跳。

2.4心跳典型值

WhatsAppLineGCM
WiFi4分45秒3分20秒15分钟
手机网络4分45秒7分支28分钟

2.5Line、WhatsApp、微信Push策略的优点

2.6Line、WhatsApp微信Push策略的不足

3. GCM研究

3.1 GCM特点

3.2 GCM心跳策略以及存在的问题

3.3 GCM的可用性及稳定性

目前测试发现GCM在国内可用性不高,原因有:

在美国3G网络下抓包的24小时,GCM的连接极其稳定,24小时内GCM长连接未曾断过,在台湾3G网络下抓包14个小时,GCM连接也只断过一次。WhatsApp用户在此类地区网络下客户端可以获得很及时的Push通知。

在中国电信3G下抓包,大部分时间GCM连接都比较稳定,只会因为偶尔的DHCP造成断连现象,由于频率很低(平均数小时才发生一次),对Push体验的影响不大。

3.4 GCM Server类型

GCM提供两种Server模型:

4.微信可能的改进点探讨

微信Push的优化主要有几个优化点:

4.1 公共Push通道

由于GCM在国内的可靠性很低,现在国内Android上的Push基本上是各自为政,很多软件都自己实现Push。导致手机被经常性的唤醒,耗电耗流量严重。

市面上已经有很多第三方的公共推送服务,大家可以选择一个适合自己应用的推送服务。腾讯也有信鸽和维纳斯组件,大家在选择方案的时候可以对比下。

最终因为我们国内外使用一套方案,并且是辅助公道,所以我们选择使用GCM。

4.2 使用GCM Push作为辅助通道

当前使用GCM的成本不大,可以使用GCM作为辅助通道来增加新消息的及时性。

使用GCM作为辅助通道,在支持GCM的设备上微信上传自己的注册GCM ID给微信Server。

微信Server在发现长连接失效的情况下,可以使用GCM 作为辅助通道通知客户端有新消息,客户端收到push通知后做一次sync。

只利用GCM来激活微信,不传递消息的具体数据,要控制给同一设备发送GCM通知的时间间隔(如五分钟)。

4.3 自适应心跳间隔优化

4.3.1影响TCP****连接寿命的因素

在Android下,不管是GCM,还是微信,都是通过TCP长连接来进行Push消息的,TCP长连接存活,消息Push就及时,所以要对影响TCP连接寿命的因素进行研究。

大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断(NAT__超时的更多描述见附录6.1)。NAT超时是影响TCP连接寿命的一个重要因素(尤其是国内),所以客户端自动测算NAT超时时间,来动态调整心跳间隔,是一个重要的优化点。

目前测试发现安卓系统对DHCP的处理有Bug,DHCP租期到了不会主动续约并且会继续使用过期IP,这个问题会造成TCP长连接偶然的断连。(租期问题的具体描述见附录__6.2)。

手机网络和WIFI网络切换、网络断开和连上等情况有网络状态的变化,也会使长连接变为无效连接,需要监听响应的网络状态变化事件,重新建立Push长连接。

4.3.2 心跳范围选择

为了保证微信收消息及时性的体验,当微信处于前台活跃状态时,使用固定心跳。

微信进入后台(或者前台关屏)时,先用几次最小心跳维持长链接。然后进入后台自适应心跳计算。这样做的目的是尽量选择用户不活跃的时间段,来减少心跳计算可能产生的消息不及时收取影响。

可根据自身产品的特点选择合适的心跳范围。

4.3.3状态转换图

图片

4.3.4自适应心跳算法描述

1、按网络类型区分计算:

因为每个网络的NAT时间可能不一致。所以需要区分计算,数据网络按subType做关键字,WIFI按WIFI名做关键字。

对稳定的网络,因为NAT老化时间的存在,在自适应计算态的时候,暂设计以下步骤在当前心跳区间逼近出最大可用的心跳。

a) 变量说明:
b) 最大值探测步骤:

图片

图4-1 自适应心跳计算流程

自适应心跳计算流程如图4-1所示,经过该流程,会找到必然使心跳失败的curHeart(或者MaxHeart),为了保险起见,我们选择比前一个成功值稍微小一点的值作为后台稳定期的心跳间隔

影响手机网络测试的因素太多,为了尽量保证测试结果的可靠性,我们使用延迟心跳测试法。
**在我们重新建立TCP连接后,先使用 短心跳连续成功三次,我们才认为网络相对稳定,可以使用curHeart进行一次心跳测试。**图4-2显示了一次有效心跳测试过程。图4-3显示了在没有达到稳定网络环境时,我们会一直使用固定短心跳直到满足三次连续短心跳成功。

使用延迟心跳测试的好处是,可以剔除偶然失败,和网络变化较大的情况(如地铁),使测试结果相对可靠(五次延迟测试确定结论)。同时在网络波动较大的情况,使用短心跳,保证收取消息相对及时。

c)运行时的动态调整策略(****已经按测算心跳稳定值后)

NAT超时值算出来后,在维持心跳的过程中的策略

图片

图4-2 后台稳定态动态调整心跳策略

4.3.5冗余Sync和心跳

在用户的一些主动操作以及联网状态改变时,增加冗余Sync和心跳,确保及时收到消息。

  1. 当用户点亮屏幕的时候,做一次心跳。
  2. 当微信切换到前台时,做一次Sync。
  3. 联网时重建信令TCP,做一次Sync

5. 可能存在的风险及预防措施

5.1 DHCP租期因素

  1. 问题: 根据目前的测试结果显示,安卓不续约到期的IP Bug,会导致TCP连接在不确定的时间点失效,从而会导致一次心跳失败。

  2. 预防: 统计后台稳定期的心跳成功率,上报给后台。后台可以按地区分网络监控这个指标的波动,并且后台可以根据不同的波动,动态调整某区域特定网络下可选的心跳区间。

5.2 其他影响TCP寿命的因素

是否有遗漏的因素?欢迎各位联系我反馈。

6 附录

6.1 附录A——NAT超时介绍

因为 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要连接 Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯。

图片

NAT 功能由图中的 GGSN 模块实现

大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT 表中的对应项,造成链路中断。下表列出一些已测试过的网络的NAT超时时间(更多数据由于测试条件所限没有测到):

地区/网络NAT超时时间
中国移动3G和2G5分钟
中国联通2G5分钟
中国电信3G大于28分钟
美国3G大于28分钟
台湾3G大于28分钟

长连接心跳间隔必须要小于NAT超时时间(aging-time),如果超过aging-time不做心跳,TCP长连接链路就会中断,Server就无法发送Push给手机,只能等到客户端下次心跳失败后,重建连接才能取到消息。

6.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。

标签:微信,GCM,Push,NAT,心跳,Android,连接
来源: https://blog.csdn.net/qq446282412/article/details/117439228