全球化应用的技术挑战
BIGO是一家高速发展的科技公司,于2014年在新加坡成立,致力于连接美好世界,传递快乐生活,成为影响10亿人生活的内容平台。所推出的产品总月活接近4亿,覆盖直播,短视频,语音社交,IM,小游戏等,用户遍及全球,包括Bigo Live,Likee,imo等。
App版本快速迭代和用户快速增长,质量与性能是一个绕不开的话题。大型App的性能优化更是一个非常具有挑战性的工作,尤其对于海外应用来讲。
首先,BIGO产品MAU接近4亿,用户遍布世界各地,庞大的用户量,复杂的应用场景和运行环境,参差不齐的设备性能和网络状况,存在各种各样的性能隐患和疑难杂症,并且很多问题非常隐蔽,表现出很强的地域相关性和网络相关性。
其次,BIGO产品最近几年一直处于高速发展阶段,产品迭代速度快,研发资源始终处于紧张状态,最快的要一周一个迭代;另外BIGO的产品不同于工具类应用,大多数属于社交产品,营收类需求较多,线上很小的缺陷也会造成很大的经济损失。
最后,也是海外市场与国内市场最大的不同,海外不同于国内自由的应用市场和宽松的规则限制,APP的发布和更新都必须经过GooglePlay和AppStore,审核与发布时间周期较长,并且不可使用国内流行的热更新等在线修复工具,出现问题后修复成本很大,必须重新提审发版来修复。
目标与挑战
面对全球化应用的技术挑战,我们提出三个问题:
● 如何实时的展示核心性能和指标走势,并在最短的时间内发现问题,发出告警?
● 如何提前问题的发现时机,避免问题带到线上,对用户体验与公司营收造成影响?
● 如何准确的定位问题发生的原因,当各种上下文信息不足,或者产生误导的时候?
这些问题对BIGO客户端质量与性能体系的建设提出了更高的要求。
首先,质量监控最好覆盖研发的各个阶段,包含开发,测试,灰度,全量;越早发现问题,越能降低对用户的影响和修复成本。
其次,性能指标最好可以实时的反映线上核心指标走势,当出现异常时第一时间通知到相关的责任人,精确到分钟级别;另外性能问题的详情和上下文尽可能的丰富和完善,帮助业务同学快速归因,定位问题所在。
最后,质量监控体系的建设最好平台化和数字化,能够快速完成已有和新增产品接入;完成产品性能的横向与纵向对比,质量周期性的快速回归,产品质量的有效衡量;以及对业务同学统一易用的使用体验,疑难与共性问题的归档等。
基于以上的问题以及要求,BIGO客户端基础架构团队设计了基本的质量监控系统工作流程图(如下),目标是客户端质量监控系统的平台化与数据化;以标准化的平台承载不同的产品,接入不同的数据;以透明,实时,准确的数据衡量产品质量,发现线上问题。
面向BIGO质量监控体系建设
背景介绍
BIGO客户端APM平台从2019年初开始立项,当时正是BIGO海外产品快速增长的阶段。当时各个产品的基础性能指标已经统一,包含崩溃,卡顿,启动速度等常规指标,同时以邮件为载体的每日性能报表已经稳定运行了半年。随着产品不断发展,研发团队增长,产品迭代变快,暴露出来的问题也越来越多,典型的问题有:
● 数据系统的割裂,开发人员需要在不同的数据系统之间切换。
● 实时性弱,性能质量报表都是以天为级别输出到业务;客户端突发问题告警的最小粒度都是小时级别;每次查询数据都需要直接到Hive查询。
● 数据透明度比较弱,由于缺乏统一的数据展示平台,数据无法在各个研发小组和研发团队之间快速流动。
● 工具链落后,问题解决链路冗长,没有统一的流程和解决进度跟踪系统,全靠口口相传,文本记录。
虽然各个子系统功能尚可,但是整体的服务和使用体验参差不齐,扩展能力弱,系统之间也不能关联,使得查找问题繁琐无比,面对突发问题也束手无策,焦头烂额。
方案调研
于是BIGO客户端基础架构团队开始着手研究业界的解决方案,包括GooglePlayVitals,Bugly或者内部的Hive+Grafana技术栈。
一番调研之后,发现并没有百分百契合内部需求的产品;官方的GooglePlay Vitals数据全面,覆盖了很多业务层面统计不到的问题,但是纯黑盒运行,不支持自定义字段,当发生问题后无法关联到产品的上下问题信息,所以只能作为参考用;腾讯的Bugly只支持崩溃率与ANR率统计,指标比较局限,也没有提供自定义新指标的接口;最后只剩下内部的Grafana平台+Hive,Grafana定位于纯粹的数据报表展示平台,缺乏详情和流程跟踪功能,定制化工作量较大;Hive的实时性偏弱,无法满足客户端产品需求。
在一番讨论之后,BIGO客户端基础架构团队决定自研,取名“灵雀APM”。
整体设计
监控整体要求就是快速发现故障、快速定位故障以及辅助进行程序性能优化。为了做到这些,我们对监控系统的一些做了如下的要求:
● 覆盖三端Android/iOS/Flutter 数据。
● 覆盖开发,测试,上线各个研发阶段的数据。
● 数据的实时性最好能到分钟级别。
● 可以方便的接入新项目和新指标。
● 跟踪流程和实时报警最好和企业微信相结合。
当时恰逢BIGO大数据团队在公司引入Druid实时分析数据库,“灵雀APM”成为第一个种子用户。
基于以上目标,BIGO客户端基础架构团队做了大量的工作,从无侵入式监控SDK的研发,基于AI的UI自动化测试系统研发,到APM性能管理平台建设,实时大数据分析平台的引入,实时报警工作流与内部IM的无缝集成等。
整体架构如下图所示:
经过一年的努力,目前BIGO质量监控体系建设日臻完善,形成了以“灵雀“APM为核心,自动化测试系统和专项分析工具为辅助的一系列平台与工具,完成开发/测试/发布研发全流程Android/iOS/Flutter三端数十个指标的覆盖和支持。
产品落地
到目前为止,“灵雀APM”已经逐步接入了公司所有的产品,包含Android/iOS,支撑单日线上过亿的设备和应用性能监控,比如核心短视频应用的某个指标每日上报数据量达100G+。
指标也从最初的崩溃,卡顿,启动速度扩展到了内存水平监控与线上分析,存储占用监控,大图监控等应用性能指标的方方面面。
利用BIGO大数据团队Druid以及后来引入的ClickHouse,线上性能数据做到了分钟级别的趋势查询和告警(下图为分钟级别的崩溃率实时曲线),这使得业务团队面对突发问题时更加游刃有余。
信息的价值会随时间锐减,尤其是事故处理过程中。
比如19年某天,Likee短视频崩溃率在单小时内暴增五倍,各方团队拉群后一筹莫展,最后通过查询“灵雀APM”崩溃率分钟级别的实时变化曲线,将问题上涨开始时间点定位到分钟级别,最后定位到时后台在那个时间点下发错误配置导致;从接到告警到定位原因,全程只花了30分钟左右。
线上问题的攻坚与突破
在完整的监控体系下,我们也发现了不少线上的疑难问题,解决过程披荆斩棘,充满了各种挑战与乐趣。
头号难题 ANR
什么是ANR
在使用Android手机时,有时手机卡顿会出现系统弹窗:应用没有响应,这就表示应用发生了ANR(Application Not Responding),下面的弹框估计每一位Android用户都不会陌生。
ANR率作为仅次于崩溃率的稳定性指标,在BIGO海外应用中,由于网络环境的复杂以及设备整体性能偏低的影响,一直居高不下,对用户影响较大;但是监控手段却乏善可陈,传统的统计方式存在各种限制和不足,ANR本身的信息又存在一定的误导,对定位解决问题帮助不大,一直是BIGO产品性能的一个头号难题。
ANR的发生原因
那么ANR警告机制是怎么发生的呢?
Android系统是基于事件驱动。当Android的四大组件(Activity, Service, BroadCast, ContentProvider)执行时,会将消息插入消息队列中。
在插入时,为了防止某些消息执行时间太长,导致影响其他消息的分发,ANR警告机制会在插入时同时在系统内"埋炸弹"。
当消息在指定时间内执行完毕并返回,那么ANR警告机制会及时"拆除炸弹",今天又是安全的一天。
可是如果某条消息没有及时返回,ANR警告机制检测到消息超时,那么会立刻"引爆炸弹"。
"引爆炸弹"会记录当前手机CPU,各个进程的运行状态,将这些信息存入一个anr文件中,这样开发者就能够通过anr文件确认ANR发生的原因及时处理它。
记录完成之后最后一步就是弹出ANR弹窗提示用户,提示当前应用无响应,用户可以选择等待或者重新启动应用。
整个流程如下图:
ANR的监控方式
目前业务常用的监控手段有以下几种:
通过对比业界的方案和结合我们自己的实际情况,我们采用了一种基于ANR产生特征的方案来实现对ANR的监控:
1.针对Service/Receiver ANR,通过Hook MainLooper MessageQueue,对Service/Receiver生命周期调用相关Message进行监控,超过ANR检测阈值未消费则认为发生一次ANR进行上报。
2.针对主线程超时导致的ANR,通过监控帧回调方法,对于帧回调方法执行间隔严重超时(暂定5s)则认为发生一次ANR进行上报。
确定了监控原理之后,定位ANR问题一般还需要结合场景、页面,logcat,完善的线程堆栈信息等一系列辅助信息,所以我们需要提供完善的ANR上下文信息进行上报,主要上报指标包括:
● 页面及轨迹
● 所有线程的Trace信息(通过动态链接libart.so调用导出符号DumpForSigQuit的方法实现)
● Logcat
● 前后台
● 主线程状态
● 当前CPU占用
优化结果
经过几个版本的迭代之后,客户端建立一套ANR的统计,查询和分析机制,主要包括:
● 多维度的ANR聚类平台建立,包括ANR率指标报表、ANR主线程堆栈聚类报表、ANR类型(Service/Receiver/主线程超时)报表等。
● 完善的ANR报警体系,做到分钟级别的报警提醒,第一时间发现问题。
● 快速定位Top问题,通过多维数据快速分析共性问题。
这套系统也落地到了短视频产品上,两个月内发现问题数十加,ANR率下降75%。
扑朔迷离的内存占用
BIGO的客户端产品多为音视频和图片重度使用者,所以内存问题一直也是性能优化面对的头号大敌;在业务开发的过程中,主要遇到以下几类问题:
1. 音视频应用,内存占用普遍较高,需求迭代快,各版本间无内存指标对比,内存指标容易随着版本迭代而劣化。
2. 测试阶段无支持自动化内存分析的工具,分析问题较为繁琐。
3. 线上OOM问题频发,难以定位,影响正常的版本迭代。
内存问题并不像崩溃一样明显,通常情况下更加隐蔽,非常难以归因,主要表现有Native崩溃率飙升,OOM,卡顿,内存泄露,GC频繁;所以解决内存问题,必须监控先行,再配以线下与线上自动化分析工具,建立内存监控和分析闭环,主要包含以下三个关键元素。
1. 建立统一的应用内存水平监控体系,输出各项内存指标,衡量应用的内存使用情况;
2. 建立核心业务场景内存压测流程,开发自动化内存分析工具,方便的暴露和定位内存异常问题;
3. 开发线上内存分析组件,分析应用内存组成及内存泄露,上报后台,聚类展示,便于业务同学解决内存问题;
内存指标的监控大概可以分为黑盒监控与白盒分析。
黑盒监控也就是内存宏观指标监控,主要维度包括各项内存数据(各类 pss、虚拟内存、线程数量等),包含应用整体内存,页面内存,内存异常 case(java 堆触顶、线程数量过多、fd 过多等);通常使用宏观指标比如TotalPss来衡量应用的整体性能以及做横向对比,对于具体的业务场景,则通过单页面内存占用去考量。
内存宏观监控上线后,效果显著,发现问题数10+,包含列表加载大图、线程泄露、SDK策略调整导致的内存增加等;下图是一个线程泄露的例子。
与宏观内存指标对应的就是内存占用白盒分析,宏观只能从整体上分析内存占用异常的页面,当得到异常后,就必须通过白盒分析来确定具体的内存占用。
我们基于 shark 的研发了高速低内存的线上分析工具,使用Lengauer-Tarjan算法(如下图)构造支配树,同时优化内存数据结构,降低内存占用和提高分析速度。
写在最后
BIGO客户端基础架构组作为基础支撑团队面向公司所有的App产品,负责相关的质量体系建设,组件与架构设计,跨平台与动态化容器研发,以及新技术探索,疑难技术攻关,保障产品快速迭代,提升产品质量和用户体验;我们支撑的产品总月活接近4亿,覆盖直播,短视频,语音社交,IM,小游戏,用户遍及世界各地,庞大的用户量,复杂的应用场景和运行环境,充满各种各样的技术挑战。
本文从宏观角度介绍了BIGO的客户端质量监控体系建设,后续还会对更多具体的技术主题展开分享我们的技术实践方案,譬如 Android内存的静态与动态分析,启动速度函数级监控,ANR监控的实现原理, iOS无损性能的卡顿监控、iOS FOOM 监控等,敬请关注。