分享一种Android端IM即时通讯智能心跳算法

对于IM或实时消息推送技术来说,客户端的心跳算法几乎是必备品,尤其当前复杂的移动网络环境下,网络心跳保活算法的优劣更是决定了您的APP即时数据收发的实时性和用户体验,非常地关键。

为什么TCP连接需要心跳?

因为运营商有一个NAT超时:因为IP v4的IP量有限,运营商分配给手机终端的IP是运营商内网的IP,手机要连接Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网IP、端口到内网IP、端口的对应关系,以确保内网的手机可以跟Internet的服务器通讯,大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰NAT表中的对应项,造成链路中断。

所以我们需要间隔一定的时间发送一个数据包来保证当前的TCP连接保持有效,这就是所谓的心跳包。

什么是智能心跳?

智能心跳实际上就是动态的探测到最大的NAT超时时间,然后选定合适的心跳间隔区间去发送心跳包,同时在网络状况发生变化的时候能够动态的调整心跳间隔时间;如果心跳间隔不合适,例如心跳间隔过短,那么可能导致频繁的唤醒手机发送心跳包,增加耗电,心跳间隔过长,可能导致这条TCP连接已经无效但是无法及时的检测到,只能等待下一个心跳包发送的时候才能感知到,所以会导致消息接收延迟,所以探测到一个合适的心跳间隔是非常重要的,把耗电和消息接收及时性综合折中来取得一个最佳的体验。

本文要探讨的二分法智能心跳策略

1心跳变量定义

探测心跳:程序采用不确定的时间间隔去发送心跳,目的是为了得到最大NAT超时时间

稳定心跳:当探测心跳探测到了NAT超时时间那么就会选定比这个时间点稍微小一点的时间来作为稳定心跳,以后就一直以这个稳定时间去发送心跳

minHeart:最小的心跳间隔

maxHeart:最大的心跳间隔

curMinHeart:初始值为minHeart,变换过程中的最小心跳

curMaxHeart:初始值为maxHeart,变换过程中的最大心跳

step:心跳探测步长

maxSuccessCount:稳定心跳成功次数的最大值,用来动态向上探测

maxFailedCount:心跳连续失败次数最大值,用来向下探测

curHeart:当前正在使用的心跳间隔,默认270秒,这个值可以根据不同地区的心跳区间大数据采集统计然后再设置

timeout:心跳超时时间,我们当前设置为20秒,这个其实可以调整的更小,5秒~10秒,之所以设置为20秒是考虑到网络很不好的情况下可能心跳返回的比较慢,所以间隔设的大一些

heartbeatStabledSuccessCount:稳定心跳连续成功的次数

heartbeatFailedCount:心跳连续失败的次数

networkTag:网络环境标识,对于数据网络来说分为电信,联通,移动;对于wifi来说是用wifi的名称来区分的,因为每个运营商的网络环境都可能有不同的NAT超时,所以在网络环境变换的时候要重新调整心跳。

上调curHeart(心跳成功的时候)

把当前的成功心跳区间保存到列表中

curMinHeart = heartbeat.curHeart;

如果当前心跳是稳定心跳,heartbeatStabledFailedCount

= 0;heartbeatStabledSuccessCount++;如果当前心跳不是稳定心跳,curHeart = (curMinHeart

+ curMaxHeart) / 2,然后直接执行第6步

判断heartbeatStabledSuccessCount是否大于maxSuccessCount,如果大于的话就上调maxSuccessCount的上限,可以乘以2,或者递增固定值,这个可以自己决定,我们是maxSuccessCount默认为20,所以maxSuccessCount

= maxSuccessCount + 20;

从成功心跳列表选择比当前稳定心跳更大一级心跳,如果有就把这个作为新的稳定心跳,如果没有:curMaxHeart

= maxHeart;curHeart = (curMinHeart + curMaxHeart) /

2;然后再重新以curHeart开始向上探测心跳

判断curMaxHeart - curMinHeart <

10是否满足,如果满足并且当前心跳还不是稳定心跳:curHeart =

curMinHeart;把二分法比较小的那个值作为稳定心跳,然后探测结束,进入稳定心跳,这里之所以这么做是因为二分法的一个特点,二分法的一个临界值就是curMaxHeart

=

curMinHeart,到最后curMinHeart和curMaxHeart很接近的时候其实(curMaxHeart+curMinHeart)==

2*curMinHeart

==2*curMaxHeart,所以会导致二分法计算出来的curHeart和curMinHeart,curMaxHeart相差就几秒,这是没什么意义的,设置一个10秒的区间来让心跳尽快进入稳定状态

下调心跳(心跳失败的时候)

heartbeatStabledSuccessCount=0;

curMaxHeart = curHeart;

如果是稳定心跳失败了,heartbeatStabledFailedCount++;并且判断heartbeatStabledFailedCount>maxFailedCount,如果是则从成功心跳列表中选择比当前心跳略小一级的心跳并把这个心跳作为新的稳定心跳,要是不存在略小一级的成功心跳,那么curMinHeart

= minHeart;curHeart = (curMinHeart + curMaxHeart) / 2;

如果是探测心跳失败了,curHeart = (curMinHeart + curMaxHeart) / 2;

判断curMaxHeart - curMinHeart < 10,如果满足并且当前心跳不是稳定心跳:curMinHeart = minHeart。

本算法的最终探测效果

以270秒作为curHeart开始探测,minHeart为60秒,maxHeart为300秒,在我们公司的wifi或者数据网络环境下:270,285,292就能够达到稳定心跳,最终稳定心跳会比292小10秒。也就是282秒作为稳定心跳,这里面大概在14分钟之内alarm了三次,如果把maxHeart上调的话探测到稳定心跳的时间会变长,不过平均alarm次数会降低,因为心跳周期在不断变长。即时通讯开发

当达到稳定心跳后,在稳定心跳成功发送20次后会再次尝试上调心跳,如果由于网络环境不稳定导致当前的心跳可能失败次数超过了5次,那么就会下调心跳,总之做到一个原则,严格控制下调条件,能不下调就尽量不下调。

和微信智能心跳算法的对比

【1】更加省电:微信智能心跳是按照从最小还是逐渐递增的去探测的,所以在网络环境不好的条件下前期可能一直探测不上来,心跳周期一直维持在一个较小的范围,导致频繁的alarm,耗电,微信智能心跳探测过程:60秒短心跳,连续发3次后开始探测,90,120,150,180,210,240,270,这个过程中一共耗费24分钟,alarm了10次,在前14分钟之内alarm了8次,而二分法智能心跳前14分钟才唤醒3次。

【2】网络环境差的情况下不会频繁的唤醒:当网络环境很不好的情况下,心跳可能会经常失败,微信智能心跳由于是从下往上上调心跳,可能一直维持在一个间隔周期较小的心跳,会频繁alarm,二分法是从上往下下调心跳,因此心跳周期是逐渐缩小,一开始不会频繁的alarm,比较省电。

【3】探测周期短:微信智能心跳是逐渐的通过累加探测步长来上调心跳,上调的趋势比较稳定,但是如果step设置的比较小,那么会导致上调缓慢,探测到稳定心跳所需要的时间比较长(24分钟);二分法智能心跳的心跳调整波动比较大,成功了就上调一半,失败了就下调一半,所以探测到稳定心跳的时间会比较短(14分钟),但是其实这个都是相对的,如果NAT超时时间为2分钟,那么微信智能心跳一下子就能探测到了,而二分法智能心跳要调整好多次,反正是看NAT超时时间距离最初开始探测的curHeat比较接近,所以curHeart可以通过大数据搜集分析,针对各个地区给出不同的curHeart。

【4】探测期间不够稳定:微信智能心跳的探测过程很稳定,基本不会导致心跳失败,因为它是从最小的开始探测;二分法智能心跳就不一样了,以为curHeart的调整波动比较大,一开始探测一下子上调或者下调一半很容易就超出NAT超时时间,在探测前期会有比较频繁的失败心跳;当然,这个也是相对的,最终都要取决与curHeart的初始值,minHeart,maxHeart,如果这些值设置的合适,那么二分法智能心跳将会很快的探测到稳定心跳。

Android机子上存在的问题

也就是Android系统里alarm的对齐唤醒问题。国内的手机厂商例如华为,魅族,小米都是自定制的android系统,对于AlarmManager都有对齐唤醒策略,因此会导致心跳alarm的时间不准确,例如设置了270秒alarm一次,但是在这些手机上可能要推迟到300秒才能唤醒,那么问题来了,如果NAT超时时间是2分钟,而这些手机的alarm最小间隔是5分钟,那就坑了,永远无法探测到最佳心跳,你设置120秒的alarm,手机系统也给你延迟到5分钟才执行alarm,不过这种情况只有在手机休眠的时候才会对齐唤醒,在手机不休眠的时候,我侧过,alarm计时还是准确的。

猜你喜欢

转载自blog.csdn.net/wecloud1314/article/details/125496947