转自: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 的机制类似。
虽道阻且长,但相信国内安卓环境会越来越好!

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

  1. 【转】推送消息推送机制

    原文链接:推送消息&推送机制 - 知乎 消息推送(push)用一句话解释就是:服务端向客户端发送了一条消息,我们在通知栏.锁屏通知.微信消息等等之类的都是消息推送. 1/推送类型有哪些? 消息 ...

  2. android开发 app消息提醒功能,Android中利用App实现消息推送机制的代码

    1.消息推送机制 服务器器端需要变被动为主动,通知客户一些开发商认为重要的信息,无论应用程序是否正在运行或者关闭. 我想到了一句话:don't call me,i will call you! qq今 ...

  3. 一篇文章带你了解APP PUSH推送机制

    本文为PMCAFF专栏作者卓别木出品 写作目的: 本文主要讲解关于APP PUSH的流程.机制及相关经验,一是为了方便各位可以针对APP迅速制定PUSH消息推送方案,实现0到1的推送功能搭建,二是可以 ...

  4. 移动手机消息推送机制

    由于公司要做一个android的消息推送功能,让我进行了一个调研,发现网上没有一个集中说明的地方,自己在网上搜罗了一些资料并且自己总结了一下. 对于消息的提醒方式可以分为四种:固定窗口.弹出窗口.手机 ...

  5. ios消息推送机制原理与实现(转)

    今天给无线事业部的同事开发苹果客户端的推送接口.无线事业部就是我们公司专门开发各种终端的app的部门啦! 无线事业部的同事做事还是很体贴的,同时发给了我参考文档地址和需要的开发需要的pl2文件. 提供 ...

  6. iOS开发如何实现消息推送机制

    Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用.net作为Provider. APNS 是Apple Pu ...

  7. 苹果消息是先推送到服务器,iPhone消息推送机制实现与探讨

    http://www.cocoachina.com/iphonedev/sdk/2011/1124/3599.html 最近两天在研究ios的消息推送机制.研究这个东西,还是充满兴趣的. Push的原 ...

  8. 客户端技术:一文带你了解iOS消息推送机制

    导语 | 消息推送我们几乎每天都会用到,但你知道 iOS 中的消息推送是如何实现的吗?本文将从推送权限申请,到本地和远程消息推送,再到 App 对推送消息的处理等多个步骤,详细介绍 iOS 中消息推送 ...

  9. Unity提供的消息推送机制

    转载出处:http://blog.csdn.net/liulong1567/article/details/46463353 概述 Unity提供的消息推送机制可以非常方便我们的脚本开发,它实现的是一 ...

最新文章

  1. java 连接oracle数据库(最简单的使用)
  2. Google团队在DNN的实际应用方式的整理
  3. VC/MFC Tips
  4. python学习笔记-练手实例
  5. Python进阶09 动态类型
  6. SAP CRM 产品主数据和附件(Attachment)的模型关系
  7. Vue 单文件中的数据传递
  8. Java数据结构的知识体系
  9. [转载]解决mysql“Access denied for user 'root'@'localhost'”
  10. 修航片调卫片,不会PS的GISer不是一个好“美工“
  11. java texttospeech_TextToSpeech 文本自动朗读
  12. 再也不用手写爬虫了!推荐5款自动爬取数据的神器!
  13. 软件设计和开发规范(国标)
  14. html涂鸦画板插件,sketchpad-简单的HTML5 Canvas涂鸦画板插件 -HTML5功能
  15. 基于历史使用数据的虚拟机动态整合研究( 文献阅读与问题理解)
  16. 基于SSM的生产计划排程管理系统
  17. QQ音乐酷狗音乐竞品分析
  18. Python数据分析2-pandas入门和实战
  19. 赠书 | 四大通证类型:价值创新的源头
  20. 前端请求报:NET::ERR_INCOMPLETE_CHUNKED_ENCODING,响应200,但接收不到正常响应

热门文章

  1. 微信读书分享群+无限卡攻略
  2. excel提取括号内的内容
  3. 运城学院计算机应用技术,运城学院学子在中国大学生计算机设计大赛中取得历史最好成绩...
  4. 对List集合属性进行模糊查找
  5. poj-openjudge 1042:Moles 解题报告
  6. PyCharm设置中文(官方插件版)
  7. api-String
  8. 进阶篇:3.5)粉末冶金件设计
  9. C语言SVPWM代码与软件测试
  10. 【Python蓝桥杯】印章 共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。