融云技术共享:融云安卓即时通讯产品网络链接保活技术实践

时间:2020-10-20

通讯软件

融云技术共享:融云安卓即时通讯产品网络链接保活技术实践

 1.介绍

 众所周知,即时消息是一项要求高度即时性的技术,确保消息即时到达的首要条件是链接存活。在复杂的网络环境和中国安卓手机的深度定制下,如何保证链接的生存?本文详细阐述了融云安卓即时通讯产品在基于TCP协议实现链路保持的实践总结。

 2.相关文章

 “为什么基于TCP的移动即时消息仍然需要心跳保持机制?》

 “微信团队原创分享:安卓版微信背景保活战斗分享(流程保活文章)”

 “微信团队原创分享:安卓版微信背景保活战斗分享(网络保活文章)”

 “移动即时通讯实践:安卓版微信智能心跳机制的实现”

 “移动即时通讯实践:WhatsApp、Line和微信心跳策略分析”

 “安卓P的官方版本即将推出:让后台应用程序保持活跃并推送消息的真正噩梦”

 “当前安卓后台保活方案实际运行效果的综合清单(截至2019年)”

 了解即时通讯应用中的网络心跳包机制:功能、原理、实现思路等。

 “融云技术共享:安卓即时通讯产品网络链接保持技术在融云的实践”

 3.信息管理系统的总体框架

 融云技术共享:融云安卓即时通讯产品网络链接保活技术的实践

 如上图所示,为了保证链路的生存,一个成熟的即时消息系统通常包括两个长连接通道:消息链路和推送链路。

 当新消息到达时,消息服务将首先判断消息链接是否有效。如果消息链接是活动的,消息将优先从消息链接发送到客户端,否则它将被路由到推送服务器并由推送链接发送。

 总之,链接保活涉及到消息链接和推送链接的保活策略。基于这两个链接的不同使用场景,除了心跳机制之外,保活策略是不同的。下面将逐一解释。

 4.保持联系的必要性

 在建立了基于TCP的套接字连接之后,该连接是否会存在并且可以长时间使用而无需任何处理?答案是否定的。

 有两个原因:

 1)默认的Socket连接不能及时检测到链路的异常情况,即使Socket的属性参数KeepAlive设置为真,也不能及时获得链路的生存状态。这是因为Socket的连接状态由状态机维护,连接完成后,双方都将处于建立状态。如果某个服务器由于某种原因过载,无法及时响应服务请求,TCP仍会检测到连接状态,但实际上此链接不再可用。

 2)国内运营商的网络地址转换超时机制会在一段时间内断开连接而不进行数据交互,这可能只有几分钟,远远不能满足我们的长连接要求。

 有关这方面的更详细的技术文章,请参见:“为什么基于TCP的移动即时消息仍然需要心跳保持激活机制?”,“微信团队原创分享:安卓版微信背景保活战斗分享(网络保活文章)”

 5.通用保活机制-心跳机制

 由于上述原因,为了使套接字连接长时间保持活动状态,有必要实现它自己的保持活动机制。

 最常见的保活机制是心跳机制。也就是说,客户机每隔一段时间向服务器发送一个小数据包,并根据它是否能从服务器接收到响应来判断链路的可用性。为了节省流量,这个包通常很小(通常越小越好,例如网易云信的即时消息云产品中的1字节心跳包被宣传为该产品的卖点),甚至没有内容。

 融云技术共享:安卓即时通讯产品网络链接保活技术在融云的实践

 那么客户端是如何实现定期发送心跳数据包的呢?通常有两种方法。

 一个是用Java中的定时器实现的。

 最基本的步骤如下:

 1)建立要执行的任务时间表;

 2)创建一个计时器实例,通过计时器提供的schedule()方法将TimerTask添加到计时器,设置为定期执行TimerTask,并在TimerTask中发送心跳数据包。该方法实现简单,省电,并且不需要保持唤醒锁定。缺点是显而易见的,在后台很长一段时间内,在进程被回收或者系统休眠之后,定时器机制将会失败。

 另一种方法是使用安卓系统的定时任务管理器AlarmManager,循环执行发送心跳包的任务。

 这种方法不会因为系统休眠而失败。在系统休眠后,它仍然可以通过唤醒锁唤醒并执行心跳任务。

 因此,与定时器机制相比,这种方法更耗电,使用时必须注意以下几点:

 1)首先,根据需要合理使用报警管理器的闹钟参数。闹钟参数的差异请参考下表:

 融云技术共享:在融云_3.png安卓平台上即时通讯产品的网络链接保持技术实践

 2)其次,AlarmManager提供了cancel()方法,在设置新的调度任务之前,取消系统中设置的相同类型的任务,以避免设置冗余任务。

 最后,安卓引入了6.0版本的瞌睡模式,并提供了一种新的闹钟设置方法setExactAndAllowWhileIdle()。通过这种方法设置的闹钟时间将由系统智能地安排,并且由每个应用程序设置的事务将在一次唤醒中处理,以节省电力。建议在安卓6.0或以上系统中优先使用此方法。

 有关这方面的更多详细技术文章,请参见:

 “应用保活的终极总结(一):安卓6.0下双进程保活的实践”

 "应用保活的终极总结(二):安卓6.0及以上的保活实践(过程反杀)"

 "应用程序保持生命的终极总结(3):保持安卓6.0及以上版本的生命实践(被杀死和复活)"

 安卓进程保持活力的详细解释:一篇解决你所有问题的文章

 "安卓端消息推送概述:实现原理、心跳保持、遇到的问题等."

 “深入讨论安卓信息推送”

 “安卓P的官方版本很快就要发布了:让后台应用保持活跃并推送消息的真正噩梦”

 “当前安卓后台保活方案实际运行效果的综合清单(截至2019年)”

 最新的建议是:“安卓从进入到放弃都保持活力:引导用户进入白名单(以七种主要型号的白名单为例)”(本文发表于2020年6月13日)。

 6.消息链接保持活动机制

 作为发送和接收消息的主要通道,消息链路需要最大限度地保证链路的可用性。当链路不可用或异常断开时,可以及时检测并启动重连保证机制。

 基于上述特征,除了上述心跳机制之外,消息链路还维护两组链路优化机制:复合连接机制和重连机制。

 复合连接机制的基本步骤如下:

 1)客户端与导航服务器连接,导航服务器将发布与应用对应的配置信息,包括连接服务器的地址列表;

 2)客户端尝试从第一个服务器地址连接,并启动超时机制。如果连接失败或没有及时收到服务响应,它将继续尝试连接到下一个,直到成功连接,并将成功连接的地址保存在本地作为最佳地址,以后连接时优先使用。通过这种机制,可以保证客户端首先选择最佳链接,缩短连接时间。

 融云技术共享:安卓即时通讯产品网络链接保活技术在融云的实践

 ▲复合连接机构的原理

 重新连接机制:在检测到与服务器的连接断开后,业务层尝试重新连接服务器n次,并在第一次断开后重新连接1秒钟。如果连接仍然不成功,它将在2秒钟后尝试重新连接服务器(重新连接间隔是最后一次重新连接间隔乘以2),依此类推。尝试重新连接n次后,服务器将不再尝试重新连接,除非网络状况发生变化或应用程序重新打开。

 融云技术共享:安卓即时通讯产品网络链接保持技术在融云的实践

 ▲重联机制原理

 7.推动链接保持活动机制

 作为消息到达的补充手段,推送链接需要尽可能延长在后台的生存时间。即使在被杀之后,他们仍然可以再次醒来。iOS手机有APNS来达到上述效果(见“理解iOS信息推送就够了:历史上最完整的IOS推送技术的详细说明”),但安卓的官方推送系统FCM在中国基本上不可用。如何确保推抵国内安卓系统?

 首先,我们需要了解安卓的两种流程管理机制:

 1)一个是LMK机制,英语是低内存黑仔,它是从基于Linux的内存管理机制派生出来的。它主要通过过程的oom_adj值来确定过程的重要性,然后决定是否回收这些过程。价值越低,重要性就越高。例如,由框架层启动的本机进程和系统进程的优先级通常是负的。其次,这个过程在前台是可见的,系统不会回收它。然而,可以看出,当流程退回到后台后,oom_adj的值将立即上升,并在系统定期清理时被杀死;

 2)另一个机制是安卓原有的权限管理机制(AppOps),由主要制造商进一步定制,如小米的安全中心和华为的手机管家,所有这些都用于权限管理。权限管理机制运行在安卓系统的框架层。如果上层的每个应用程序的进程想要尝试重新启动,系统将首先检查该进程在权限管理中心是否具有自启动权限,如果是,则允许启动。否则,系统的启动直接受到框架层的限制。

 基于以上两种机制,推送链接的保活可以分为两类。

 第一类:进程保持活动状态:

 其思想是根据LMK机制提高进程优先级,降低被杀的概率。

 主要有以下几种方法:

 1.1)监控黑屏事件并启动1像素透明活动:将应用程序流程转化为可视化流程并降低被杀死的概率。屏幕打开时,关闭“活动”。

 1.2)双重服务监护人:服务a以开始前台()的形式启动并发送通知,而服务b以开始前台()的形式启动并发送与a具有相同标识的通知,然后调用服务b中的停止前台()方法来取消通知。这样,服务将以后台进程的形式存在,而不会影响用户的感知。

 1.3)根据文件锁互斥原理,监控Java进程的生存状态:如果被杀死,Linux层成功保存文件,然后打开一个纯Linux可执行文件,通过exec()命令启动一个守护进程,在Android 5.0之前有更高的优先级,因为它是从Linux层启动的。在安卓5.0之后,这种方法不再有效。

 第二类:进程激活策略与安卓系统的AppOps机制有关:

 通常有以下几种类型:

 1)使用服务本身的Sticky属性,在服务的onStartCommand()中返回START_STICKY,这样当服务被终止时,系统将自动尝试重新启动。然而,在中国的定制系统中,以这种方式成功重启的概率非常低,并且用户需要在权限管理中心中打开自启动和其他权限才能成功拉活;

 2)这也是前面提到的心跳机制,但是在这里需要使用AlarmManager来设置具有EXHERATED _ REALITY _ WAKE属性的闹钟。系统休眠后,它通常会接收心跳事件,从而激活进程;

 3)通过监控网络切换和用户行为等事件来启动流程;

 4)应用程序之间相互吸引。例如,如果系统中的几个应用程序集成了同一个SDK,当用户启动其中一个应用程序时,SDK将扫描其他应用程序,并使“兄弟姐妹”栩栩如生。这种方式对用户体验非常有害,会造成系统无法解释的功耗。

 请阅读以下“黑色技术”的详细介绍文章:

 “应用保活的终极总结(一):安卓6.0下双进程保活的实践”

 "应用保活的终极总结(二):安卓6.0及以上的保活实践(过程反杀)"

 "应用程序保持生命的终极总结(3):保持安卓6.0及以上版本的生命实践(被杀死和复活)"

 随着安卓版本的迭代,对后台进程启动的控制越来越严格。为了解决推送问题,每个手机制造商都推出了自己的系统级推送服务。制造商在框架层维护一个推送通道,上层的所有应用程序一起使用推送链接,因此不需要维护单独的流程。目前,支持系统级推进的厂商有小米、华为、魅族、vivo和OPPO。

 鉴于安卓系统对后台进程的控制越来越严格,保持活力的“黑色技术”不再有效:

 “安卓P的官方版本即将推出:让后台应用程序保持活跃并推送消息的真正噩梦”

 “当前安卓后台保活方案实际运行效果的综合清单(截至2019年)”

 在后安卓时代,请阅读以下两篇文章:

 “2020年,安卓在后台还能继续生存吗?看看我如何优雅地实现它!》

 “历史上最强的安卓保持活力思维:深入分析腾讯TIM的过程永生技术”

 “安卓进程永生技术的终极揭示:进程杀戮的基本原理,应用对抗杀戮技巧”

 整合第三方系统级推送后,整个消息发送和接收过程可以参考下图:

 融云技术共享:安卓即时通讯产品网络链接保活技术在融云的实践

 这种系统级推送节省了电力、内存和高到达率。根据不同的手机型号,应用程序可以在制造商的系统级别优先推送,然后配合自己的保活机制,最大限度地保证推送的到达率。