国内APP消息推送机制以及微信消息延迟问题剖析

转自:https://club.huawei.com/thread-15878044-1-1.html

一、前言
随着安卓手机以及QQ/微信/支付宝/滴滴出行/美图外卖等一大批移动通信/移动消费应用的日益普及,我们无时无刻不在享受着这些移动产品带来的便利;但同时也会遇到一些困扰,比如QQ/微信/支付宝消息延迟、微信/支付宝收款无语音播报、滴滴出行/美图外卖商家版在后台不能及时接单等问题,这些问题归根到底还是Android应用消息推送服务体验差。
移动互联网时代,消息推送是移动应用的一项重要功能,今天我们来聊聊聊APP消息推送机制,顺带着为大家解决微信消息延迟问题。

二、国内APP消息推送机制
目前中国安卓系统生态环境尚不成熟,设备碎片化现象严重,导致不同应用与操作系统在适配性方面产生了一系列问题,消息推送服务也会遇到各种障碍。虽然在安卓手机上谷歌有推出GCM服务,由于GCM需要google service支持,在国内基本不能用。那么,Android系统上的应用又是如何在没有使用GCM服务的情况下把消息推送给我们的呢?有如下三种方式:
1、使用第三方推送SDK
这是谷歌服务在国内运行情况不佳的产物,国内有多家第三方推送服务比如腾讯信鸽,百度,极光,个推,小米等,需要APP接入SDK,但是第三方推送服务可能会被系统杀掉,所以不同手机系统中不同第三方推送的消息到达率/及时率参差不齐。
2、接入厂商统一推送
为了优化消息推送成功率,降低电量和流量消耗,很多手机厂商也开始为开发者提供系统级推送服务,比如EMUI系统的华为推送、MIUI系统的小米推送、Flyme系统的魅族推送等,部分开发者为了提升消息及时性会选择集成主流的几家推送,根据设备进行区分,小米设备使用小米推送、华为设备使用华为推送、其他设备使用第三方推送。
3、开发团队自研发推送功能
开发团队自研发推送功能需要投入开发成本、服务器/带宽成本,以及后期维护成本,而且推送效率并不一定比第三方高,大部分开发团队会选择介入第三方推送。
当前像微信这种超级应用,毋庸置疑肯定会选择自研发。接下来,我们看下微信的消息推送机制。

三、微信消息推送机制
在Android下,不管是GCM还是微信,都是通过TCP长连接来进行推送消息的,TCP长连接存活,消息Push就及时。
所以,微信想要做到消息及时推送,不止微信客户端要后台保活,TCP长连接也要保活。
1、如何保活TCP长连接
1)网络状态变化时及时重连

网络状态发生变化比如手机网络和WIFI网络切换、网络断开和连上时,TCP长连接变为无效连接,所以微信会监听网络状态变化事件,及时重建长连接。
2)及时发心跳包防止NAT超时
因为IP v4的IP(即公网IP)有限,无法满足人类使用(中国人用都不够),所以运营商分配给手机终端的IP是运营商内网的IP,手机要连接Internet,就需要通过运营商的网关做一个网络地址转换(NAT)。简单的说运营商的网关需要维护一个外网IP、端口到内网IP、端口的对应关系,以确保内网的手机可以跟Internet的服务器通讯。
大部分网络运营商在链路一段时间(几分钟或者十几分钟)没有数据通讯时,会淘汰NAT表中的对应项(即NAT超时),从而内、外网IP之间再无法对应,造成TCP长连接无效。说到这里,可能大家都想到了防止NAT超时的方法:客户端间隔一定时间发送一个心跳包给服务器,及时刷新NAT表,并告知服务器客户端当前的状态;所以心跳包的主要作用是防止NAT超时,其次是探测连接是否断开。
2、微信智能心跳方案
为了保证微信收消息及时性的体验,当微信处于前台活跃状态时,会使用固定心跳;当微信进入后台(或者前台灭屏)时,微信会使用智能心跳。
智能心跳实际上就是先用几次最小心跳维持长链接,然后动态的探测到最大的NAT超时时间,再选定合适的心跳间隔区间去发送心跳包,同时在网络状况发生变化的时候能够动态的调整心跳间隔时间。
如果心跳间隔不合适,例如心跳间隔过短,那么可能导致频繁的唤醒手机发送心跳包,增加耗电;心跳间隔过长,可能导致这条TCP连接已经无效但是无法及时的检测到,只能等待下一个心跳包发送的时候才能感知到,所以会导致消息接收延迟。
所以探测到一个合适的心跳间隔是非常重要的,把耗电和消息接收及时性综合折中来取得一个最佳的体验,这个也是微信使用智能心跳的原因。

四、微信延迟问题原因揭秘
上文有提到,微信想要做到消息及时推送,不止微信客户端要后台保活,TCP长连接也要保活(及时发送心跳),当然保持网络始终连接是前提条件。
原因1:锁屏断网
各大厂商均为用户提供了"休眠状态下是否保持网络连接"的开关,如果对微信消息及时性要求高的同学,可以选择"始终"。
以华为EMUI5.X系统为例,设置路径为:
1)进入手机设置>WLAN>配置>在休眠状态下保持WLAN连接,选择始终;
2)进入手机设置>更多>移动网络>始终连接数据业务,打开开关;

不过我发现,现在华为最新EMUI8.X系统上,即使不选择“始终”,微信也可以及时收到消息,应该是华为意识到微信消息的重要性,对微信加了白名单。
原因2:运营商NAT超时时间较短
根据微信官方文档介绍,最小心跳为4.5min,但是国内有些地区有些运营商设置的NAT超时时间比较短(小于4.5min)。在这种网络下,如果是灭屏状态,微信的TCP长连接基本上每隔几分钟就会断开,直到重连后才可以收到消息,加上目前各大厂商的省电策略,本身应用在后台就非常不活跃,可能无法及时重连,这个就导致微信延迟概率更高、延迟时间更久。
这种网络很容易识别,如果你在4G网络下/其他运营商WiFi下不会延迟,只在特定网络下比如家里的WiFi下高概率延迟,并且多个系列的安卓机都会延迟,那么很可能是因为你使用网络的NAT超时时间比较短。
针对这类网络,曾经在贴吧见过网友给过一个解决办法:打电话给运营商客服,要求把宽带帐号加到外网。不过很多网友质疑可行性,然后楼主说是找在电信的朋友给加的。这个操作虽然理论上可以解决延迟问题,但是的确没有可行性......
所以,遇到这种网络,如果不想换网络,但是又希望微信消息及时接收的话,只能祈祷微信缩短最小心跳间隔,并且手机厂商不进行管控(所以我说了一堆废话......)。

原因3:后台清理微信
待机时长是用户挑选机型时首要考虑的一个因素,手机发热耗电快也是用户吐槽非常多的一个问题。所以电池大小、充电速度、系统省电策略也是谷歌包括各大厂商在不断改进(有可能越改越瞎)的事情。
当应用进入后台或者系统灭屏时,能杀的全都杀掉:不在用户保护名单里,杀!高耗电应用,杀!不听话应用,杀!
如果对微信消息及时性要求高的同学,最好把微信加入清理白名单。
以华为EMUI5.X系统为例,设置路径为:手机管家>剩余xx%>锁屏清理应用,将微信设置成锁屏后不清理;
不过微信现在作为超级应用,基本没有厂商敢在后台杀微信的了,而且基本都会将微信加入受保护白名单,想一键清理也清理不掉,只有停止运行微信才可以,估计也有部分用户会觉得很闹心。

原因4:谷歌省电策略
1)Android 5.0:JobSchedule(对齐唤醒机制)

在待机状态下,如果系统和App没有发出动作,安卓其实是很省电的。不过,安卓App频频唤醒后台,令安卓耗电大增。App每次唤醒设备1到2秒,待机时间就会减少2分钟。这并不仅仅指的是点亮屏幕,还有系统在处理应用的后台任务。
谷歌在Android 5.0上提出API JobScheduler,系统可以批处理一些应用唤醒要求,减少电量消耗,也叫做对齐唤醒机制。
当然,谷歌的这个对齐唤醒机制需要应用主动调用,并且是针对不需要准时执行并且希望批量处理的任务,所以并不会影响微信消息的及时推送。
2)Android 6.0:Doze模式、App Stanbdy
谷歌在Android 6.0上提出了两个省电特性(Doze模式、App Stanbdy)以延长电池使用时间。
如果一个用户断开充电连接,灭屏不动手机一段时间之后,系统会尝试延缓app后台的CPU和网络活动(延缓应用的任务、同步和标准alarms,阻止应用访问网络)减少电量的消耗。
当然应用可以通过适配来保证基本功能正常运行,用户也可以选择将应用加入白名单。
以华为EMUI8.X系统为例,设置路径为:设置>应用和通知>应用管理>设置>特殊访问权限>忽略电池优化>微信,设置为允许。
原因5:厂商省电策略
各大厂商的省电策略相比谷歌省电策略,更加复杂粗暴,并且应用根本无法适配。目前了解到的厂商省电策略主要有如下几种:
1)后台断网/后台清理
上文提到,估计除了超级应用可以幸免于此了。并且有些APP即使加入白名单,依旧会被清理。
2)对齐唤醒机制
上文提到,谷歌在Android 5.0上提出的对齐唤醒机制并不会影响微信消息的及时推送;但是厂商的对齐唤醒机制比较粗暴,会将所有应用在一定时间段内的多次唤醒合并成一次唤醒,减少系统被唤醒次数,增加待机时间。
而微信心跳就依靠这个定时器,在唤醒的时候发送心跳给服务器,如果被厂商对齐唤醒,心跳间隔就会比原本设定的长(比如从4.5min变成10min),那么使用网络NAT超时时间<10min的这部分用户就会出现NAT超时,微信消息出现延迟。

而不同厂商的针对不同应用、在不同时间段的对齐时间可能还不一样。
情况1:如果你白天不会延迟,只有晚上/半夜会延迟,那么很可能是厂商在夜间做了省电策略,夜间对齐唤醒时间间隔比较久。
情况2”如果你在4G网络下/其他运营商WiFi下不会延迟,只在特定网络下比如家里的WiFi下高概率延迟,并且其他系列手机均不会延迟,那么很可能是因为你使用的这款机型的对齐唤醒时间间隔比较久(当然前提是手机上所有开关都设置好)。

手机厂商的这种做法,虽然为用户节省了功耗,但是却没有给用户足够的选择权,因为有些用户相比节省功耗优先会选择消息及时性。
值得鼓励的是华为EMUI8.X系统在近期更新的版本上给了用户选择权,当用户选择允许后台活动后,不再对微信做对齐唤醒等管控。设置路径为:
在设置>电池>启动管理,找到微信,关闭"自动管理",打开"手动管理"的三个开关"允许自启动""允许关联启动""允许后台活动"。
不过当前已经支持的版本并不多,只看到了P20系列 B108版本、Mate10系列 B129sp03版本。不过各位使用华为手机的朋友还是可以期待下,毕竟旗舰产品已经带了,其他产品肯定也会陆续带上~


五、微信消息延迟问题-华为手机相关开关汇总
由于本人使用华为机比较多,针对华为手机统一整理了相关开关,其他厂商机型可以自行百度。
场景1:如果打开微信没有地球界面,说明微信在后台没有被杀,你需要进行如下设置:
如果是EMUI8.X产品:

1.允许微信后台活动可以通过设置允许微信后台活动,提升微信接收消息及时性,操作步骤:
在设置>电池>启动管理,找到微信,关闭“自动管理”,打开"手动管理"的三个开关“允许自启动”“允许关联启动”“允许后台活动”。
注:当前已支持产品与版本有P20系列 B108版本、Mate10系列 B129sp03版本;其他EMUI8.X产品后续应该会陆续推送版本
2.将网络设置为始终连接
1)进入手机设置>无线和网络>WLAN>配置>在休眠状态下保持WLAN连接,选择始终;
2)进入手机设置>无线和网络>移动网络>高级>始终连接数据业务,打开开关;
3)进入手机设置>无线和网络>移动网络>高级>WLAN/移动数据连接切换提示,选择自动使用移动数据连接。
3.将微信设为忽略电池优化 设置>应用和通知>应用管理>设置>特殊访问权限>忽略电池优化>微信,设置为允许。
4.关闭省电模式 点击手机管家>剩余xx%,关闭省电模式和超级省电的开关。
5.关闭省流量模式 手机管家>流量管理>省流量模式,关闭省流量模式;如果需要使用省流量模式,请打开微信应用的开关,关闭后将无法在后台接收新消息。
6.开启系统的通知功能 在设置>应用和通知>通知管理中找到微信,根据需要设置允许通知,以及通知方式(在状态栏、横幅、锁屏显示通知)。
7.开启微信应用内部的通知功能 在微信我>设置>新消息提醒,打开“接收新消息通知”开关,并根据需要打开或关闭“通知显示消息详情”、“声音”、“震动”。

如果是EMUI5.X产品:
1.将网络设置为始终连接
1)进入手机设置>WLAN>配置>在休眠状态下保持WLAN连接,选择始终;
2)进入手机设置>更多>移动网络>始终连接数据业务,打开开关;
3)进入手机设置>更多>移动网络>WLAN/移动数据连接切换提示,选择自动使用移动数据连接;
2.将微信设为忽略电池优化 设置>应用管理>设置>特殊访问权限>忽略电池优化>微信,设置为允许;
3.关闭省电模式 点击手机管家>剩余xx%,关闭省电模式和超级省电的开关。
4.关闭省流量模式 手机管家>流量管理>省流量模式,关闭省流量模式;如果需要使用省流量模式,请打开微信应用的开关,关闭后将无法在后台接收新消息。
5.开启系统的通知功能 在设置>通知栏和状态栏>通知管理中找到微信,根据需要设置允许通知,以及通知方式(在状态栏、横幅、锁屏显示通知);
6. 开启微信应用内部的通知功能 在微信我>设置>新消息提醒,打开“接收新消息通知”开关,并根据需要打开或关闭“通知显示消息详情”、“声音”、“震动”。 :

场景2:如果打开微信有地球界面,说明微信在后台被杀,所以你无法及时收到消息,你需要进行如下设置:
如果是EMUI8.X产品:
1.将微信设置为自动管理的应用:手机管家>剩余xx%>启动管理,将微信设置成自动管理。
2.系统提示微信高耗电提醒时,不要将应用直接关闭;
3.在使用手机管家>剩余xx%中一键省电时,如果清理了微信,需要手动再次开启微信。
4.超级省电模式下,微信会被关闭,如果手机电量充足,不需要使用超级省电时,最好关闭超级省电(手机管家>剩余xx%)
如果是EMUI5.X产品:
1.将微信设置为后台活跃应用和允许自启动应用
  后台活跃设置:手机管家>剩余xx%>锁屏清理应用,将微信设置成锁屏后不清理;
自启动应用设置:手机管家>自启管理,将微信勾选成允许开机自动启动;
2.系统提示微信高耗电提醒时,不要将应用直接关闭;
3.在使用手机管家>剩余xx%中一键省电时,如果清理了微信,需要手动再次开启微信。
4.超级省电模式下,微信会被关闭,如果手机电量充足,不需要使用超级省电时,最好关闭超级省电(手机管家>剩余xx%)


六、结束语
想要彻底解决微信消息延迟问题,除了配置上面的相关开关外,还需要微信、运营商网络、厂商省电策略这三个模块统一进行优化。这么一看,还是2017年10月份工信部牵头成立的"安卓统一推送联盟"比较靠谱点。
按照工信部泰尔终端实验室说法,未来将由终端厂商提供系统级推送服务,不再允许各 app 在后台保留常连接。与此同时,各终端厂商实现推送通道接口和功能统一,方便开发者接入。在新标准下,消息将通过统一的服务器推送至用户设备,而不必唤醒应用,与 iOS 的机制类似。
虽道阻且长,但相信国内安卓环境会越来越好!

猜你喜欢

转载自blog.csdn.net/blueangle17/article/details/83996422