微信Android客户端后台保活经验分享
suiw9 2024-11-05 12:35 67 浏览 0 评论
“
本文首发于InfoQ垂直公众号『移动开发前线』。【ID:bornmobile】分享嘉宾:杨干荣,微信Android客户端基础平台、性能优化负责人
保活,按照我们的理解包含两部分:
网络连接保活:如何保证消息接收实时性。
进程保活:尽量保证应用的进程不被Android系统回收。
1.0 网络连接保活
网络保活,业界主要手段有:
a. GCM
b. 公共的第三方push通道(信鸽等)
c. 自身跟服务器通过轮询,或者长连接
国产机器大多缺乏GMS,在国内GCM也不稳定(心跳原因),第三方通道需要考虑安全问题和承载能力,最后微信选择使用自己的长连接。而国外, GCM作为辅助,微信无法建立长连接时,才使用GCM。
之前看到大家在聊各种Java网络框架,而微信实际上都是没用上的。早年的微信,直接通过Java socket 实现。微信v5.0后,考虑各系统平台的统一,开始使用自研c++组件。
长连接实现包括几个要素:
a. 网络切换或者初始化时 server ip 的获取。
b. 连接前的 ip筛选,出错后ip 的抛弃。
c. 维护长连接的心跳。
d. 服务器通过长连notify。
e. 选择使用长连通道的业务。
f. 断开后重连的策略。
今天主题在保活, 我们重点讨论心跳和 notify 机制。
1.1 心跳机制
心跳的目的很简单:通过定期的数据包,对抗NAT超时。以下是部分地区网络NAT 超时统计:
上表说明:
a. GCM无法适应国内2G环境(GCM 28分钟心跳)。
b. 为了兼容国内网络要求,我们至少5分钟心跳一次。
老版本的微信是4.5分钟发送一次心跳,运行良好。
心跳的实现:
a. 连接后主动到服务器Sync拉取一次数据,确保连接过程的新消息。
b. 心跳周期的Alarm 唤醒后,一般有几秒的cpu 时间,无需wakelock。
c. 心跳后的Alarm防止发送超时,如服务器正常回包,该Alarm 取消。
d. 如果服务器回包,系统通过网络唤醒,无需wakelock。
流程基于两个系统特性:
a. Alarm唤醒后,足够cpu时间发包。
b. 网络回包可唤醒机器。
特别是b项,假如Android封堵该特性,那就只能用GCM了。API level >= 23的doze就关闭所有的网络, alarm等。但进入doze条件苛刻,现在6.0普及低,至今微信没收到相关投诉。另Google也最终加入REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限。
1.2 动态心跳
4.5min心跳周期是稳定可靠的,但无法确定是最大值。通过终端的尝试,可以获取到特定用户网络下,心跳的最大值。
引入该特性的背景:
a. 运营商的信令风暴
b. 运营商网络换代,NAT超时趋于增大
c. Alarm耗电,心跳耗流量。
动态心跳引入下列状态:
a. 前台活跃态:亮屏,微信在前台, 周期minHeart (4.5min) ,保证体验。
b. 后台活跃态:微信在后台10分钟内,周期minHeart ,保证体验。
c. 自适应计算态:步增心跳,尝试获取最大心跳周期(sucHeart)。
d. 后台稳定态:通过最大周期,保持稳定心跳。
自适应计算态流程:
在自适应态:
a. curHeart初始值为minHeart , 步增(heartStep)为1分钟。
b. curHeart 失败5次, 意味着整个自适应态最多只有5分钟无法接收消息。
c. 结束后,如果sucHeart > minHeart,会减去10s(避开临界),为该网络下的稳定周期。
d. 进入稳定态时,要求连接连续三次成功minHeart心跳周期,再使用sucHeart。
稳定态的退出:
sucHeart 会对应网络存储下来, 重启后正常使用。考虑到网络的不稳定,如NAT超时变小,用户地理位置变换。当发现sucHeart 连续5次失败, sucHeart 置为minHeart ,重新进入自适应态。
1.3 notify机制
网络保活的意义在于消息实时。通过长连接,微信有下列机制保证消息的实时。
Sync:
通过Sync CGI直接请求后台数据。Sync 通过后台和终端的seq值对比,判断该下发哪些消息。终端正常处理消息后,seq更新为最新值。
Sync 的主要场景:
a. 长连无法建立时,通过Sync 定期轮询
b. 微信切到前台时,触发Sync(保命机制)
c. 长连建立完成,立即触发Sync,防止连接过程漏消息
d. 接收到Notify 或者 gcm 后,终端触发Sync 接收消息.
Notify:
类似于GCM。通过长连接,后台发出仅带seq的小包,终端根据seq决定是否触发Sync拉取消息。
NotifyData:
在长连稳定, Notify机制正常的情况下(保证seq的同步)。后台直接推送消息内容,节省1个RTT (Sync) 消息接收时间。终端收到内容后,带上seq回应NotifyAck,确认成功。这里会出现Notify和NotifyData状态互相切换的情况:
如NotifyData 后,服务器在没收到NotifyAck,而有新消息的情况下,会切换回到Notify,Sync可能需要冗余之前NotifyData的消息。终端要保证串行处理NotifyData和Sync ,否则seq可能回退。
GCM:
只要机器上有GMS ,启动时就尝试注册GCM,并通知后台。服务器会根据终端是否保持长连,决定是否由GCM通知。GCM主要针对国外比较复杂的网络环境。
2.0 进程保活
在Android系统里,进程被杀的原因通常为以下几个方面:
a. 应用Crash
b. 系统回收内存
c. 用户触发
d. 第三方root权限app.
原因a可以单独作为一个课题研究。原因c、d目前在微信上没有特殊处理。这里讨论的就是如何应对Android Low Memory Killer。
下面分享几个微信保活的方法:
2.1 进程拆分
上图表述的是微信主要的几个进程:
a. push主要用于网络交互,没有UI
b. worker就是用户看到的主要UI
c. tools主要包含gallery和webview
拆分网络进程,确实就是为了减少进程回收带来的网络断开。
可以看到push的内存要远远小于worker。而且push的工作性质稳定,内存增长会非常少。这样就可以保证,尽量的减少push 被杀的可能。
这里有个思路,但限制比较多,也抛砖引玉。启动一个纯C/C++ 的进程,没有Java run time ,内存使用极低。
这种做法限制很明显,如:没有Java run time ,所以无法使用Android系统接口。缺乏权限,也无法使用各种shell命令操作(如am)。但可以考虑一下用途:高强度运算,网络连接,心跳维持等。比如Shadowsocks-android就如此,通过纯c命令行进程,维护着socks5代理 (Android M运行正常)。
tools进程的拆分也同样是内存的原因:
a. 老版本的webview 是有内存泄漏的
b. Gallery大量缩略图导致内存使用大
微信在进入后台后,会主动把tools进程kill掉。
2.2 及时拉起
系统回收不可避免,及时重新拉起的手段主要依赖系统特性。从上图看到, push有AlarmReceiver, ConnectReceiver,BootReceiver。这些receiver 都可以在push被杀后,重新拉起。特别AlarmReceiver ,结合心跳逻辑,微信被杀后,重新拉起最多一个心跳周期。
而对于worker,除了用户UI操作启动。在接收消息,或者网络切换等事件, push也会通过LocalBroadcast,重新拉起worker。这种拉起的worker ,大部分初始化已经完成,也能大大提高用户点击微信的启动速度。
历史原因,我们在push和worker通信使用Broadcast和AIDL。实际上,我一直不喜欢这里的实现,AIDL代码冗余多, broadcast效率低。欢迎大家分享更好的思路或者方法。
2.3 进程优先级
Low Memory Killer 决定是否杀进程除了内存大小,还有进程优先级:
上表的数字可能在不同系统会有一定的出入,但明确的是,数值越小,优先级越高。对于优先级相同的进程,总是会把内存占用多的先kill。提高进程优先级是保活的最好手段。
正常情况下微信的oom_adj:
而被提高优先级后:
从统计上报看,提高后的效果极佳。
原理:Android 的前台service机制。但该机制的缺陷是通知栏保留了图标。
对于 API level < 18 :调用startForeground(ID, new Notification),发送空的Notification ,图标则不会显示。
对于 API level >= 18:在需要提优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的 ID。Stop 掉InnerService ,这样通知栏图标即被移除。
这方案实际利用了Android前台service的漏洞。微信在评估了国内不少app已经使用后,才进行了部署。其实目标是让大家站同一起跑线上,哪天google 把漏洞堵了,效果也是一样的。
相关推荐
- 俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)
-
发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...
- 如何强制所有流量使用 HTTPS一网上用户
-
如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...
- https和http的区别(https和http有何区别)
-
“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...
- 快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别
-
什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...
- 简述HTTPS工作原理(简述https原理,以及与http的区别)
-
https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...
- 21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)
-
HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...
- 一次安全可靠的通信——HTTPS原理
-
为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...
- 为什么有的网站没有使用https(为什么有的网站点不开)
-
有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...
- HTTPS是什么?加密原理和证书。SSL/TLS握手过程
-
秘钥的产生过程非对称加密...
- 图解HTTPS「转」(图解http 完整版 彩色版 pdf)
-
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...
- HTTP 和 HTTPS 有何不同?一文带你全面了解
-
随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...
- HTTP与HTTPS的区别,详细介绍(http与https有什么区别)
-
HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...
- 一文让你轻松掌握 HTTPS(https详解)
-
一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...
- 如何在Spring Boot应用程序上启用HTTPS?
-
HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...
- 一文彻底搞明白Http以及Https(http0)
-
早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)