APM从入门到放弃:可用性监控体系和优化手段的剖析

在移动互联网时代,一款应用是否成功,用户体验是一个关键的因素。APM的发展使得用户体验越来越完善,本文通过90年代互联产品性能优化的发展过程到今天移动互联网时代下的APM可用性监控体系,如何去解决日渐复杂的业务导致功能不断迭代所突发的致命bug,以及日益增长的用户和膨胀的数据导致流量过大所出现的一些问题。

在《黑客帝国》电影中较为经典的一幕是让Neo在红药丸和蓝药丸中做出选择。红药丸作为一个跟踪程序,帮助Neo定位物理身体位置,无论在哪里,出现任何问题都能够第一时间定位并解决。而开发者基本都知道,想解决大部分的功能性问题的难点基本就在定位上,而电影里面出现的一些人工智能、机器学习、虚拟现实的技术,也只能够在科幻电影中才能看到。



季度活跃设备增长趋势

今天,在移动终端爆发以及用户需求的推动下,移动应用的数量和“体量”不断在急速扩大,APP性能数据在优化产品上变得越来越重要,国内大批APM厂商仿佛一夜间遍地开花,整个监控体系也从服务端到APP端再到H5端不断的加强和改变策略来适应不同的场景需求,使得监控和优化的本质上已经发生了变化。

APM的雏形发展

在90年代末,互联网还处于发展时期,PC应用因受限于网络的限制,反应速度远远无法满足大家在那时商业起步阶段的捞金热情。在1996年的时候,Tivo与HP公司就从应用程序层面出发,开发了应用响应管理开发包,他们认为网络无疑就是应用的速度。直至后来,互联网随着一些故障、带宽、数据管理等问题的出现,APM雏形才慢慢的建立起来。

1998年的时候,面向商业化管理的APM产品出现,到以组件为中心基础建设监控,分别从系统、中间件、数据库等方面监控,这也是APM发展的中期。但是在这段时间里,IBM、CA、Oracle、HP这些厂商提出的APM概念在整个行业里增长缓慢,每年的增长率不到10%,这是因为早期的APM主要是重系统,轻交互,跟飞快发展的IT环境格格不入,没有面向用户,周期过长,运维人员维护成本较高,易用性非常低,最终没有形成完整的标准化产品。

从2007年开始,整个无线互联网刚刚起来,很多企业在性能优化上大部分的精力都放在自己的PC端业务上,真正关注移动性能优化是在2011-2012年,当时移动设备的普及,APP应用市场的爆发,人们开启了全新的移动访问方式。大家在生活、娱乐、社交等都离不开移动应用,此时,大家对于性能体验的要求也越来越苛刻。

在这个时候,国外的APM行业New Relic和AppDynamics已经在APM领域拔得头筹,国内一些APM厂商看准移动的这个趋势,APM仿佛一夜之间遍地开花,直至今日,作为国内比较具有代表性的APM厂商有:听云、OneAPM、云智慧、博睿等,当前BAT领域也跻身这一领域,阿里百川-码力APM也在云栖大会中发布公测。开发者无需从零开始构建性能探针、数据平台和控制台,就可以通过可视化、可运维的方式长期监控应用性能、及时解决应用中存在的问题。

▲ APM 业务与 IT 发展关系变迁

APM可用性度量体系

如今,国内APM业务竞争越来越激烈,大家纷纷在可用性、用户体验上发力。比如,大家用手机淘宝,明显感觉稳定性和流畅度比国内其他电商APP好很多,这不仅仅是因为他们有一堆优秀的a开发工程师,更关键是其背后那一套监控度量体系。。阿里技术专家陈武认为,在性能优化方面,以往的度量是通过APP的打开率来进行对比,很多都是非常主观。但是度量体系里面面临的一个很大的问题是常态化。接着,陈武举例说明,开发团队在发布下一个APP版本的时候很难做到沉淀,比如沉淀文档、沉淀经验。对于适应整个激烈的竞争市场,很难做到敏捷。那么,在可用性上,应该如何建立起这一套度量的体系呢?

1、 可用性度量

从可量化到可视化,可量化是指客户端能够采集足够多维度下的性能指标。通过服务端对数据的加工形成一个可视化的报表,这些报表能够反映用户真实的使用场景。在可视化报表中,我们将影响用户使用的性能指标分为3级别。1,app可用性 2,服务可用性 3,性能体验。

App可用性最常见的就是crash,当用户出现crash之后大部分用户会直接卸载app。服务可用性,包括网络连接和服务端错误,这种情况可能会导致短暂的资损,如果不能迅速恢复也会导致用户流失。性能体验,主要包括慢交互,卡顿,h5的等待时间等等,这些性能指标会直接影响用户使用时长。

2、 体验度量

体验是APP对用户留存的关键,大家对APP使用过程中“如丝般顺滑”都具有天然的好感。但是目前市场上还有很多APP的体验非常差,从卡顿、闪退、耗电、延迟到占用内存被系统退出。这个时候,非常需要有一个系统去陈列和度量。

在性能优化的量化过程如何帮助企业去做定制?陈武认为,一条关键的路径需要所有的URL整合在一起,这是非常重要的健康度指标。比如通过网络监控,开发者无需对所有的URL都需要关注,可能不同的开发者关注的业务不同,大家关注的URL也不一样。在通过电商的场景,一个关键的路径是用户通过登录,打开商品,进入详情,然后下单到支付,这是一条非常关键的路径,通过把对应的关键路径所有的URL整合在一起,才能够强化业务的稳定性。

APM的可用性检测方式

▲ 阿里百川APM的监控体系

对于加强应用的可用性,APM一般都采取应用监控结合服务监控的形式,使得开发者实现端到端的全链路性能管理。在阿里百川APM监控体系中,阿里巴巴技术专家熊奇介绍了阿里百川码力在监控体系里面的应用监控、服务监控、数据库以及消息推送等性能监控,主要通过以下方式来完成:

★ 在应用监控上,采集了iOS、Android应用的内存、CPU、崩溃、网络等方面的性能数据;

★ 在服务监控上,支持Tomcat、Jetty、JBoss容器和Spring、Struts等框架的性能检测;

★ 支持MySQL等SQL数据库和Redis、Mem cache等NoSQL数据库的性能检测;

★ 阿里百川码力还提供了支持淘宝消息服务TMC、分布式框架Dubbo、淘宝API调用的性能检测。

对于数据采集之后会统一进入可以承载海量数据的存储系统和日志系统,统计系统会利用落地的数据完成数据的计算处理、生成报表,帮助开发者长期跟踪应用和服务的性能,而告警系统则会根据规则在问题发生时发出短信、邮件等即时告警,从而帮助开发者及时解决问题,降低损失。

可用性的度量检测方式-性能

在应用开发时,程序错误、主线程卡顿和资源使用超过系统限制导致的崩溃,是最严重、也是需要首先解决的问题。

通常开发者会借助模拟器、Instrument或者自动化测试发现一部分问题,但是测试往往难以覆盖用户使用场景下的设备、网络等环境。如果借助于社交媒体或者邮件反馈渠道,虽然可以有限的拿到真实的用户反馈,但是用户往往不能清楚的描述出复现问题所需的信息,往复沟通成本极高。所以,在客户端上,我们通过以下检测方式来收集应用崩溃信息。

阿里百川码力在信号捕获方式中,通过sigaction设置信号中断时的回调,这样,就可以在回调中根据程序运行状态生成对应的崩溃日志。此外,对于SIGARBT(abnormal termination),我们还需要通过NSSetUncaughtExceptionHandler来获取未捕获异常的堆栈,来补全崩溃信息。

而后,把崩溃日志上报到阿里百川码力,会依据崩溃日志的堆栈信息,聚合同一类型的崩溃后写入数据存储。同时,告警系统可以依据崩溃次数、崩溃率等规则,即时发出告警。

此外,阿里百川码力提供了dSYM上报脚本,在Xcode的build phrase中添加脚本,就可以在编译成功后自动上报dSYM文件到阿里百川码力。我们会解析dSYM文件,重新聚合后写入数据存储,聚合可以减少高达90%数据库行数;同时,还实现了崩溃日志符号化服务。不依赖mac环境符号化,更好的利用云计算平台,来服务更多开发者。

第二种技术是卡顿检测,卡顿检测的基础是RunLoop,通过RunLoop Observer监听主线程RunLoop状态的变更。在这里,把RunLoop当作在操场上跑圈的运动员,把Before Sources当做每圈的起点,同时另外开启一条线程作为计时员,每5秒判断一次RunLoop是否跑过一圈。如果5秒内RunLoop没有完成一次RunLoop,则视为主线程卡顿。在发现主线程卡顿后,会生成卡顿日志,如果是复现的卡顿,可以选择不重复上报。

此外,针对设备不同的运行时期,如启动阶段、后台阶段、空闲阶段,我们会动态调整阈值,降低检测的开销。

对于无法通过信号捕获、卡顿检测的崩溃,阿里百川码力APM引入了应用中止检测,中止检测虽然不能还原崩溃现场,但是可以揭示问题的存在。在应用进入active状态时,阿里百川码力APM在持久存储上设立一个标志位,表示程序在正常运行。在应用退出active状态或检测到崩溃时,阿里百川码力APM就清除持久存储上的标志位,表示程序在已知的情况下退出。这样,在下一次应用启动时,如果持久存储上的标志位为真,则说明应用上一次运行在未知情况下退出,这种情况阿里百川码力APM就计为应用非正常中止上报。

同时,为了过滤因为电量耗尽导致的关机,阿里百川码力APM还增加了电量检测,在低电量时,清除标志位,避免中止误报。

可用性的度量检测方式-网络

请求错误、流量开销高、被运营商劫持等网络问题是应用开发时另一类棘手的问题。当然我们也可以借助模拟器、Instrument或者自动化测试发现简单的网络问题,但是测试难以覆盖复杂的用户网络环境,也难以导出网络性能数据进行长期比对监控。如果使用手工埋点的方式记录网络性能,一方面,我们需要应对多种系统网络接口,另一方面,我们需要同步应用网络代码和埋点代码,维护成本将会居高不下。

为了监控应用在真实网络环境中的性能,阿里百川码力APM中引入了无痕埋点的网络性能监控,在网络检测中引入三种注入技术,帮助开发者长期监控应用的网络性能,优化产品用户体验。

第一种是Method Swizzling。每一个NSObject类都包含一个isa指针,指向objc_class结构体,而每一个objc_class结构体又包含一个methodLists指针,指向objc_method_list结构体数组,在objc_method_list里又包含一个objc_method结构体成员,且每一个objc_method包含一个method_imp指针,指向方法实现。

因此,只要能修改method_imp的值,我们就能替换原有的实现。在<objc/runtime>中,通过class_getClassMethod和class_getInstanceMethod取得objc_method结构体指针,而后通过method_getImplementation取得方法的原始实现地址originIMP,之后在imp_implementationWithBlock生成新实现imp的参数block里,调用原始实现,就可以原有行为前后加入网络性能埋点行为。最后调用method_setImplementation替换方法实现。这样,任何调用都将使用新的实现。

第二种技术是Proxy。在Objective-C里,NSProxy是除NSObject外唯一的根类。NSProxy是一个实现了NSObject协议的抽象类,它的正常运作需要子类override -methodSignatureForSelector:方法为sel提供方法签名,以及-forwardInvocation:方法来完成调用的转发。

使用Proxy来注入NSURLConnection、NSURLSession等对delegate的回调。具体来说,在delegate proxy收到消息时,如果不是目标协议方法,则通过消息转发机制,转发给原delegate;如果是目标协议方法,则直接调用proxy实现,在proxy实现中委托调用原delegate;此外,多数协议和协议方法都是可选的,因此,在proxy的实现中需要实现-conformsToProtocol:和-respondsToSelector:方法来声明proxy额外加入的协议和方法。这样,我们就能在不影响原有回调的同时,增加网络性能埋点逻辑。

第三种技术是fishhook。使用fishhook来替换动态链接库中的C函数实现,具体来说是CFNetwork和CoreFoundation中的相关函数。这里,以开车的模型来解释动态链接。设想一名新手司机开车从巴黎到罗马,因为他不知道路线,于是他先去咨询老司机;老司机告诉他正确的线路,这一次他可能还会绕点路,但下一次,他就会按照老司机的建议直接开到罗马。

相应的,在程序运行时,动态链接的C函数dynamic(...)地址记录在__DATA segment下的__la_symbol_ptr中;初始时,程序只知道dynamic函数的符号名而不知道函数的实现地址;首次调用时,程序通过__TEXT segment中的__stub_helper取得绑定信息,通过dyld_stub_binder来更新__la_symbol_ptr中的符号实现地址;这样,再次调用时,就可以通过__la_symbol_ptr直接找到dynamic函数的实现;如果我们需要替换dynamic函数的实现,只需要修改__la_symbol_ptr即可。具体的实现方式,可以参阅Facebook的开源框架fishhook。

加强可用性的优化手段

通过以上两种检测方式,基本能够大部分的性能和网络需求,使得开发者能够满足如今移动互联网下用户的苛刻的需求,那么,建立起来的度量体系后,了解的具体的问题后,我们应该如何去解决这些问题来提升可用性呢?

1、网络安全

运营商、DNS被劫持问题是应用开发时一类棘手的问题, 解决方案也比较多。51信用卡技术总监汪睿认为,51信用卡作为金融属性的产品,基于安全考虑会放在第一位。解决方案主要是基于全栈HTTPS的方案来处理,但会带来一些成本和性能上的损耗。甚至可以像FaceBook、google等一些解决方案,使用HTTP2.0方式,这取决于公司和开发者自身去评估实现的成本。汪睿还介绍了早起的一个过渡方案,那就是HTTP的DNS方式,通过获取一个IP表通过IP来直接连接,可以避免HTTP劫持的问题。

而网络是一个端到端的技术,阿里高级技术专家陈武认为,从电商的场景看,首先要保证服务端的稳定性,服务端可以有反刷,限流,单元化,异地容灾,服务降级等策略保证连接的稳定性。另外,客户端的角度主要看连接链路和数据量。链路里面资源可以做多CDN的备份,通过HTTP DNS或者HTTPS,HTTP2.0来反劫持。在链路稳定的基础上,接着去保证传输的效率,这里面可以通过就近接入,连接复用,提升压缩率,使用二进制协议等技术来减少包大小。当然,这里面最重要的是端到端的网络监控体系,这样在网络服务治理上会更有抓手。

2、系统降级

降级的解决方案,是系统性能保障的最后一道防线,从性能优化的角度上说,没有100%完善的设计,总会有一些意料突发的情况导致性能恶化。所以,在系统设计时,必须做好降级设计。

饿了么移动首席架构师王朝成认为,在饿了么517大促活动上,服务器端承受非常大的压力,这个时候会通过降级部分服务的方式,来确保大促秒杀这种场景得以正常运行。但是,在用户端上,以及APP,还在不断积极的发送用户请求和数据,反而增加服务器集群的压力。这个时候,王朝成表示,他们会考虑把一部分的SDK或者APP上的服务也进行降级,来减少服务端在分析数据上的压力。

降级分为手动降级和智能降级,在策略上分为流量降级、效果降级、功能性降级。流量降级主要表现在通过主动拒绝处理部分流量早餐部分用户服务不可用。而效果降级和功能性降级都表现为服务质量的降级,一个是通过在流量高峰时期用相对低质量、低延时的服务来保障所有用户的服务可用性,另外一个是通过减少功能的方式来提高用户的服务可用性。

3、网络性能

从数据结构上,需要根据不同的业务场景来选择合适的数据结构,在数据流量较少的情况可能客户端上表现不出什么区别,当在数据流量过大,且数据结构复杂的时候很可能就是直接影响到APP的性能。

类似餐饮领域“饿了么”这样的应用,数据发送的频率使得据量会非常大,对用户来说可能没有什么感知,但是商家接收大量的订单,数据量影响很大,感知比较明显。王朝成认为,可以考虑一些新的协议(Protobuf, Flatbuf)来优化数据量,比如HTTP2.0可以压缩http协议的header,使用encoder来减少需要传输的header大小,通过通讯双方各自cache一份header fields表,对于相同的数据不再通过每次请求和响应发送,又减少了需要传输的大小。再一个是采取二进制的协议,只认0和1的组合,通过把原来http1.x的header和body部分用frame重新封装,实现方便且健壮。通过内容压缩与并发传输机制,在低速、不稳定的无线条件下,较少其http body的发送大小,改善用户体验和资源效率。

▲ http1.x和http2.0协议关系

同时,阿里高级技术专家陈武也表示,如果在链路没有问题的情况下,那么必须在整个网络传输层要尽量快,不然很容易出现timeout。所以,第一要从协议层,在协议层里面通过http2.0来减少包头的压缩,同时支持服务端push消息,且通过双通通道,对通道复用更快。第二是从数据层,数据可以通过二进制压缩。在整个网络连通率较低的时候,将打包拆成小包,达到很好的传输效果。

4、动态热修复

所谓热修复,就是使用热补丁动态修复技术,通过向用户发送Patch,在用户无感知的情况下完成一些致命bug的修复。51信用卡客户端负责人汪睿认为,在移动客户端上最大的一个问题是发版,对于iOS的用户来说,整个修复流程比较漫长。需要提交审核,但是在这段时间有可能已经错过很多用户。他认为,热修复技术能够很快并及时的在线进行修复,通常在使用的过程中就完成的修复过程。

在热修复技术上,Android常用的是基于Android dex分包方案,而iOS可以利用JSPatch,它可以使得你用JavaScript书写原生iOS APP,只需要在项目中引入极小的引擎,就可以用JavaScript调用任何的Objective-C的原生接口。

总结

以上所谈到的性能优化手段基本是为了解决三种情况所造成的问题:1. 日渐复杂的业务导致功能不断迭代所突发的致命bug修复方式,2. 日益增长的用户和膨胀的数据导致流量过大,3.网络安全和内存开销的问题。

本文通过不同的场景来分析移动性能优化的模式,可以通过确定场景下解决某一类型的问题。当然,我们不能仅仅通过了解性能优化所解决的问题以及手段,更重要的是需要清楚该问题所发生的场景、原因需要的成本。

【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】

【责任编辑: 林师授 TEL:(010)68476606】

作者:林师授来源:51CTO.com|2016-10-25 13:34

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值