Android推送技术研究

来源:互联网 发布:淄博seo 编辑:程序博客网 时间:2024/06/06 19:01

Android推送技术研究

前言

       最近研究了一下的Android推送技术并参与了一款Push产品的开发和设计。此文为一个简单的总结,有些地方有疏漏,还请大家指出。


一、推送技术基础

       消息推送技术在当前手机应用中使用的非常广泛。通常推送功能的实现主要有以下几种方式:

1.     轮询(Polling)

       Polling是指客户端以一定周期或不定时查询服务器有没有新的消息需要接收,若查询到新消息,客户端只需要从服务器将消息拉取下来就行。此种方法设计简单,其实时性取决于轮询周期的长短,轮询周期短则实时性较好,但是对手机电池的消耗较大;轮询周期长虽然对手机电池消耗小,但是实时性太差。轮询对一些实时性要求不高的应用来说很为适合。在邮件客户端中,轮询的技术很为常见。

2.     短消息推送 (SMS Push)

       SMS push是通过发送二进制短信到移动终端,来达到通知终端的目的。客户端拦截这类短信,解析短信PDU的数据,然后采取相应的操作。若解析到为有新推送消息,则去连接服务器拉取消息。此技术实时性很高,但需要拦截短信解析内容,有一定安全风险;同时由于几乎没有免费发送短信的网关,推送成本较高,也需要运营商支持。因此实际中采用此技术的应用并不多。

3.     TCP长连接

       此种方法是客户端和服务器之间保持一条长的TCP连接,当有新消息到达时,服务器直接通过长连接通知客户端即可。此种方法实时性很高,但是对手机电量消耗严重,特别是当多个应用各种维持一条长连接的时候,会导致手机电量的迅速消耗。但是由于其高实时性、免费的特点,绝大多数的应用都采用此种技术来实现推送功能。

 

       注:一些过时或因某些限制国内无法使用的推送框架或技术如XMPP、GCM等不在讨论之列,读者可自行查询相关资料。

 

二、TCP长连接的实现:心跳机制

   当客户端和服务器建立连接以后,若在一定时间内没有数据交互,则该连接会被切断(运营商、系统等为了节约资源而回收)。因此,为了使连接不被中断,即使客户端和服务器直接没有数据交互,也会定时发送一些简单的数据包给对方,以防止连接被切断,从而实现TCP连接的保活,这些数据包就被称为心跳包。所谓“心跳机制”就是定时发送一个自定义数据包,让对方知道自己“在线”。以确保TCP连接的有效性。

   心跳机制中最关键的心跳周期应该为多长。若心跳周期过长,则连接可能会被回收,若心跳周期过短,则又会消耗更多电量。因此,最优的心跳周期应该是在保证连接不被中断的前提下,能达到的最大周期。本文主要讨论推送技术中心跳策略。

三、心跳策略

1.      固定心跳周期

       固定心跳周期是指两次心跳包之间的间隔是固定的,此种虽然方法简单,但效果不是很好。如前文所述,当心跳周期过短时,手机频繁唤醒,导致电池电量的急剧消耗;当心跳周期过长时却又容易被切断连接。在实际使用中,固定周期往往被设置为5分钟,这是因为移动运营商的网关在没有数据交互时会在5分钟后切断连接释放信道(2G网络时)。选取具体的心跳周期时应考虑运营商、网络类型、信号强度等因素。不同运营商、地区或不同网络类型(Wifi环境或数据业务,数据业务又区分GSM/TDCDMA/CDMA/LTE等)时,运营商或系统回收空中信道的时间不一样。当网络制式为WCDMA网络时我尝试过每15分钟发送心跳,连接也没有被切断。在采用固定心跳周期的应用中,4分钟或5分钟的心跳周期是比较常见的。

2.      自适应心跳算法

       和固定心跳周期不同,自适应心跳算法的心跳周期是变化的。一般来说,都是选取一定的区间范围或一个初始值,然后以一定步长进行探测,当服务器能及时响应时,说明连接未中断;当服务器响应超时时说明连接中断,而上一次未超时的心跳周期则是最优周期,即保证连接不被中断的最长周期。找到最优心跳之后则以固定心跳周期发送心跳包。其流程如下图所示,首先确定一个心跳区间,并去该区间最小值为心跳间隔初始值,如果服务器能及时响应,则之后每次心跳间隔递增固定步长直到服务器超时或者大于心跳区间最大值。


 

四、心跳调整策略

1.      成功一次认定,失败多次认定。

       在网络不稳定甚至无网络等场景下,可能会导致连接失败。连接时若失败因立即进行重连,多次失败后才认定是网络较差,从而进入抑制模式,节约电量。要失败多次认定的原因是为了避免因偶然因素导致的连接失败。与此相反,失败可能是偶然的,而成功是绝对的,连接成功则代表网络通畅,应立即退出抑制模式。

2.      多次失败时进行阶梯间隔抑制

       当网络不稳定甚至无网络时,多次连接失败后若无抑制模式,将会导致手机在后台反复重连服务器,导致流量和手机电量的急剧消耗,影响用户体验。所谓抑制模式指的是当连接失败时,若累积次数达到一定次数,则应认为处于网络异常状态,此时应增大重连服务器的时间间隔,达到节省流量和电量的目的。例如,当应用连续3次连接服务器失败,我们可以认为这时网络异常,不让应用立即进行重连服务器操作,而是隔一定时间后(如1分钟)后再进行重连;若1分钟后还是无法连上服务器,则之后每次连接服务器间隔递增30秒,当连接间隔达到5分钟时,还是无法连接上服务器,则之后间隔不再递增,以5分钟的周期尝试建立连接,直到连接上服务器为止。

3.      避免临界值

       在得到最优心跳间隔以后,建议采用比最优心跳稍小的值作为之后的固定心跳,而不是采用最优心跳这个临界值,避免因偶然因素导致的连接中断,提高连接的稳定性。如若探测到的最优心跳为10分钟,则可以采用9分50秒作为固定心跳周期,这样可以用较小的代价提高通道的稳定性。

4.      心跳动态调整

       可考虑以下两种情景:

a.      当用户在某地区某种网络下,成功找到最优心跳并以10分钟中的固定周期来发送心跳,当用户到另一地区或另一网络时,若此时网关支持最大的心跳周期小于十分钟,如5分钟,则应用的心跳连接会每次都中断并重连,降低用户体验。

b.      当用户在某地区某网络时,应用在寻找最佳心跳时由于某种偶然因素导致心跳响应超时,如当探测周期为5分钟时超时,应用误以为此时已达到最佳心跳,之后便以固定周期4分30秒发送心跳包,而实际上此时网关支持的心跳间隔可能远大于5分钟,如10分钟。此时,造成了不必要的流量和电量消耗,降低了用户体验。

       考虑以上两种情景,因此在找到固定心跳周期后有必要仍对心跳周期进行动态调整。调整策略可根据实际需求和大数据统计来得出。如可以在连续30次发送固定周期心跳包之后,若连接仍正常保持,则有理由怀疑此时的心跳间隔过小,因此此时可以考虑以当前心跳间隔为初始值重新寻找心跳;当连续3次发送固定心跳周期都未能及时响应,则有理由认为此时心跳间隔过大,因以最初的初始值进行重找心跳,或以当前心跳作为初始值,以一定步长进行递减来寻找心跳。

五、公共Push通道

       由于大多数手机上同时安装了多款使用推送服务的应用。若各个应用都采用自家的推送通道连接,则前文提到的心跳策略将显得毫无意义。因为各个应用的心跳周期不同步,会导致手机频繁唤醒,另外,维持多个通道也会造成电量和流量的快速消耗。而前文提到的心跳优化策略在此种情况下,显得杯水车薪。

       举个例子,如果我手机上同时安装了QQ、微信、微博三款应用,若这三款都使用私有的推送通道,且其心跳周期不同步。比如,QQ是在12:00发第一个心跳包,之后以5分钟的周期发送固定心跳包;微信在12:02发第一个心跳包,之后以5分钟的周期发送固定心跳包;微博在12:04发送第一个心跳包,之后以5分钟的心跳发送固定心跳包。虽然3款应用的心跳间隔都是5分钟,但实际上手机在每五分钟之内都会被唤醒3次。若需要推送服务的应用的数量进一步增多,那手机几乎被一直唤醒,手机的电量和流量会在短时间内急剧被消耗掉。解决此问题的方法主要有统一心跳周期和采用公共通道,由于统一心跳周期难度较大,实际中往往采用公共的Push通道。所谓公共的Push通道是指手机上需要使用推送服务的应用都使用同一条TCP长连接。前文一笔带过的GCM(Google Cloud Messaging)就是Google提供的一条公共的Push通道,但由于Google在天朝被墙,GCM在国内的可靠性极低,所以在国内基本无人使用。现在主流的公共Push通道主要是一些第三方的推送服务平台(如腾讯信鸽)和手机大厂推送平台(如华为Push、小米Push)。若是有海外版本的应用,可以考虑在两套方案:国内使用一款主流的推送平台,国外使用GCM。

       说到公共Push通道,不得不提一下Apple的推送服务。由于IOS上统一使用苹果信息推送服务(APNS,ApplePush Notification Service),而Google自家的GCM在国内是瘫痪状态,所以在消息推送上Android被IOS虐的体无完肤。下图是APNS的大致流程,Android的主流推送平台的流程都基本上是照抄APNS的。首先是应用进行token的申请,申请时会携带设备标识,APNS服务器收到申请token请求后根据请求中的设备标识生成token并存入数据库,然后再返回token给应用。此时token和此设备是一一对应关系。应用收到token后将token上报给应用服务器;当应用服务器有消息需要下发给应用A时,将需要下发的消息和该应用上报的token发给APNS服务器,APNS服务器根据token查询到对应的设备和应用并将消息下发给对应的设备弹出通知。


六、影响通道寿命的因素

       不管采用私有Push通道还是公共Push通道,所有的Push通道都是一条TCP长连接,从而来接收服务器下发的推送消息。TCP连接寿命长,通道稳定不断开,推送消息就及时,影响到连接稳定性的因素主要有以下几种:

1.      NAT超时

       由于IPV4的地址有限,运营商分配给手机的都是运营商内网的IP,手机连接外网,需要通过运营商的网关做一个网络地址转换,即NAT(Network Address Translation)。换言之,运营商的网关需要维护一个外网IP、端口到内网IP、端口的映射关系,以确保内网手机可以访问外网。当通信链路在一定时间内没有数据交互时,大多数移动运营商都会淘汰掉NAT表中的对应项,造成链路的中断,即前文说的网关中断连接。NAT超时是影响TCP连接寿命的一个重要因素。TCP长连接的心跳间隔必须小于NAT的超时时间。一般NAT与运营商及网络制式相关,如移动的2G网络NAT超时为5分钟(这也是为什么大多数采用固定心跳Push的周期间隔为5分钟的原因),而联通4G的NAT大于15分钟。所以应用客户端需要根据网络类型来自动测算NAT超时时间,同时服务器也可以根据大数据统计来下发相关心跳数据,以此来动态调整心跳间隔,达到最优的心跳。

2.      DHCP租期

       DHCP租期到期后Android不会主动续约,这会导致TCP连接的偶然性中断。

3.      网络状态变化

       手机网络状态变化(数据业务、Wifi网络切换,网络断开和连接)时,通道会中断,此时应监听网络变化事件,在对应的事件到来时重新建立连接,确保通道的稳定性。

4.      网络类型变化

       不同运营商、不同网络类型(GSM/LTE/WIFI等)NAT超时时间不同,在心跳调整时,因考虑不同的网络类型,针对不同运营商和网络类型,可考虑不同的心跳周期策略(如心跳区间范围、步长等)。

七、结语

       这里主要讨论的是端外推送,实际在工作中还有一些其他的问题和细节,一时想不起来,后面有时间会逐步完善,文章写的仓促,不到之处也欢迎大家一起讨论。


0 0
原创粉丝点击