IM 推送保障及网络优化详解(一):如何实现不影响用户体验的后台保活

对于移动 App 来讲,IM 功能正变得愈来愈重要,它可以建立起人与人之间的链接。社交类产品中,用户与用户之间的沟通能够产生出更好的用户粘性。
在复杂的 Android 生态环境下,多种因素都会形成消息推送不能及时达到客户端。另外,不稳定的移动网络也给数据传输的速率和可靠性增长了障碍。
本文详解了网易云信 IM SDK 在应对弱网环境、移动端硬件限制以及 Android 复杂的生态现状时的探索与心得。如何实现不影响用户体验的后台保活,改善的长链接加推送组合方案,以及在弱网环境大数据传输的优化实践。linux

带着思考阅读:

1.什么是 IM
2. IM SDK 如何实现不影响用户体验的后台保活
3.如何作长链接加推送组合方案
4.如何在弱网环境下优化大数据传输

IM 的定义

IM 由两个字组成:Instant, Messaging
即时性要求有新消息时可以当即收到,若是程序在后台,则要能当即收到推送通知。
通讯则要求稳定可靠,系统不宕机,程序不崩溃,安全,传递消息时不会被拦截监听,消息不丢,顺序不乱,不重复,若是包含音视频聊天,则要求延迟低,流畅不卡顿。

图片描述

要真正作出一套稳定可靠的商用级 IM 系统,挑战很是大。
第一个问题是消息推送。iOS 有 APNS 作推送,至关稳定。Android 自己也有GCM 能够用,可是在国内有“墙”,直接就把 GCM 等等 Google 的服务所有挡在外面。为了实现即时稳定的消息推送,从易信时代开始,网易就开始研究,随着时间的推移,困难和方法也在不停的变化。
对于 IM,当 App 退到后台,是必须还可以收到新消息提醒的,没有 GCM,怎么办?在最初,惟一能作的,就是后台运行了。这几乎是接收推送的惟一途径,就算是到如今,也是最主要的途径。Android 从设计上,就是支持真后台运行的,后台运行的特性也是 Android 如今能如此成功的缘由之一,但另外一面,Android 长久以来一直摆脱不了的卡顿,耗电等坏名声,后台运行也拖不了干系。所以,系统对于后台运行也不会听任自流。android

App 在后台运行所面对的四大障碍

第一个障碍是 Android 的 Low Memory Killer 机制。手机的内存有限,当后台运行的进程愈来愈多,内存剩余量也就随之减小。当有一个新的 APP 想要启动,若是内存不够,LMK 机制就会启动,从正在运行的进程中挑选一个清理掉,释放出空间,而后新的 APP 就能够运行了。
LMK 有两个尺度去评判。一个是进程优先级,优先级越低,被清理的可能性越大,另外一个是内存占用,占的内存越多,被清理的权重天然也越大。
由于 LMK 机制的存在,虽然 APP 容许在后台运行,但一样也面临随时被清理的风险。所以,网易须要在被清理后及时的从新启动。常规的,有4种方式可以作到。git

  • 第一个是 sticky service
就是在 Service 的 onStartCommand 中返回sticky flag,这样当 service 被 kill 掉后,系统会将它加入重启的 pending 列表,在后面合适的时机再把 service 重启。
  • 第二个障碍是 alarm
闹钟,有循环闹钟和一次性闹钟两种,在闹钟触发后启动对应的组件。
  • 第三个障碍是在 Manifest 文件中静态注册的 Receiver
经过监听各类系统事件,好比开机,网络变化,mount/unmounts 等,在这些事件发生时启动组件,由于这种方式会形成在这些事件发生时系统容易卡顿,在 7.0 里面,Android 增长了限制。
  • 第四个障碍是 JobScheduler
这是在 5.0 里面新增的,容许 App 在特定事件发生时作一些动做,好比充电,切换到 wifi 等。

虽然说不管怎么作,App 终究免不了一死,但经过对照 LMK 的评判准则,仍是能够下降APP被清理的几率的。第一个就是下降进程的内存占用。若是采用单进程的模式,因为进程中包含了 UI,Webview,各类图片缓存等内容,内存必然会居高不下,降不下来。IM 软件通常都会采用双进程甚至多进程的策略,将 push 进程独立出来,在 push 进程里只处理网络链接和 push 业务,不参与任何其余业务逻辑,更不包含任何 UI。github

如下是网易云信 Android SDK 的架构,按照分层的结构模式设计。最底下青色的一层是 push 层,他就是做为一个独立进程运行的。他只负责处理网络长链接的相关工做,好比安全加密,心跳,鉴权,封包解包等工做,全部业务逻辑都交给UI进程的服务模块去作。来看一下云信 Demo 的进程内存占用状况。上面一个是主进程,看第四列 PSS 的数据,内存占用是 50M 左右,下面一个是 push 进程,内存占用只有 10M 左右。当处于后台时,push 进程被清理几率比 UI 主进程低不少。算法

图片描述

下降被清理几率的第二个手段是提高进程优先级。先看这个例子,这是绿色守护的一个截图,最上面是“暂不自动休眠”,由于这里列出的两个 App 的状态都是工做中,对应的进程优先级是“可视进程”。但这两个 App 并无提供桌面小部门在运行,也没有指示前台服务的常驻通知栏提醒,事实上,他们就只是在后台运而已。一般进程退到后台后,其进程优先级类型就变成了较低的后台进程,而不是这样的“可视进程”,他们是经过什么方法来提高优先级,下降被清理几率呢?缓存

图片描述

Android 在设计前台服务上有一个漏洞,经过两个服务配合就能建立一个隐形的前台服务。这里有两个已经启动的 Service: A 和 B。先在 A 中调用 startForeground,提供一个 NOTIFY_ID, 而后 A 就变成前台服务了,同时有了一个 ID 为 NOTIFY_ID 的常驻通知栏提醒,而后网易在 B 中也调用startForeground,提供相同的 NOTIFY_ID, B 也变成了前台服务,由于两个通知ID相同,所以这一次就不会建立新的通知栏提醒了。而后再在 A 中调用stopForeground,A 的前台属性被取消,同时,常驻通知栏提醒也会被移除,可是,Service B 并不会受到任何影响,仍是前台服务,这是再把 A 停掉,进程就只剩下前台服务 B 了,进程也变成了前台进程,但用户不会有任何感知。安全

正常来讲,作了上面 3 步以后,进程就可以比较稳定的在后台运行了。网络

但在有些状况下,推送进程却永远起不来。跟踪以后发现,除了系统可以杀掉后台运行的进程外,用户也同样是能够杀死进程的。用户杀掉进程的方式有两种,一种是在最近任务列表中将 App 划掉,这种方式和系统杀掉进程效果相同。另一种就是经过这里的 force stop,这种方式比系统清理更加完全。不但 App正在运行的进程会被清理,app 当前在重启列表中的待重启服务,注册的各类闹钟,事件监听组件等都会被移除,除非用户在主动点击或者系统重启等外力,App 无法再本身从新爬起来了。
在有些国内的像 MIUI 一类的 ROM 上,用户从最近任务列表中将 App 移除,效果居然也是 force stop。正常来讲,若是是用户主动操做,App 自己也不该该再重启了。但有些时候这个并非用户本意,何况,对于 IM 软件来讲,消息推送是必定要获得保障的,不然不明正确的吃瓜群众们会以为是软件不行,连消息推送都作很差。架构

APP 安卓进程保活的好办法

第一个是经过两次 fork 加上 exec 的方式。两个 fork 后,第一次 fork 的进程退出,第二次 fork 出来的进程就会被 init 进程领养。用户此时再 force stop,由于这个进程复进程是 init,而不是 Zygote,所以不会被清理。因为这个进程仍是从 android 进程 fork 出来的,带有 android 运行时环境以及复进程的资源,因此内存会比较大,这里能够再经过 exec 命令,打开一个纯 linux 的可执行文件,开启一个 daemon 进程,其内存占用大概只有 100K+,对用户也就彻底无感了。利用这个后台进程,能够定时的将 push 进程拉起来。此种方式只在 5.0 如下的系统中有效,在 4.4 及以上系统中,SELinux 特性是强制开启的,exec 没有权限执行,同时在 5.0 以后,ActivityManager 在作 force stop 以及移除任务时,只要是具备相同的 uid 的进程,就会所有清理掉,再也不漏掉没有虚拟机环境的进程。app

最后一个后台保活的手段是一个大杀器,也是带有强烈的中国特点。由于前面所列的全部保活手段都不是那么保险,所以想出来这么一个互相保活的方式。当一个 App 进程起来后,他就去扫描已安装的应用列表,看看有没有本身的兄弟姐妹,好比说同一个长的 App,或者是集成了同一个 SDK 的 APP,若是有,就把这些 App 都拉起来。这也就是如今比较出名的“全家桶”方案。虽然说这种方法确实可以带来较高的后台存活率,特别是那些大厂和应用普遍的 SDK,可是这种方式对于用户的伤害也很是大,若是有后台推送的必要性,且不会对用户体验形成太大伤害时,此方式还可使用,但若是只是为了推广告,则会对用户形成伤害,反过来,也可能会致使用户直接卸载 App。

如今各类手机管理软件都会对这种全家桶唤醒方式作限制,特别是在 root 过的机器上,能够作到彻底切断这些唤醒路径。同时,不少 ROM 也会自带管理软件,限制后台运行和后台唤醒,以便给设备换取更长的续航。在目前国内的 Android 生态环境中,不管采用什么方式,想要一直在后台运行时愈来愈难了,须要从新想另外的办法来保障消息推送。另外一方面,做为开发者,也有义务为用户提供更好体验的软件,而不是无休止的在后台浪费用户的资源。


随着即时通信以及音频处理和压缩技术的不断发展,效果更好、适用范围更广、性能更高的算法和新的技术必将不断涌现,若是你有好的技术或者分享,欢迎关注网易云信官方博客和 GitHub:

关注更多技术干货内容: 网易云信博客
欢迎关注 网易云信 GitHub
欢迎关注 网易云信官网
相关文章
相关标签/搜索