【APMCon 2016】饿了么移动技术负责人胡彪:浅谈App优化

如需转载请联系听云College团队成员小尹 邮箱:yinhy#tingyun.com

中国应用性能管理行业盛宴——2016中国应用性能管理大会(简称APMCon 2016)于8月18日至19日在北京新云南皇冠假日酒店隆重召开。APMCon由听云、极客邦和InfoQ联合主办的作为国内APM领域最具影响力的技术大会,首次举办的APMCon以“驱动应用架构优化与创新”为主题,致力于推动APM在国内的成长与发展。

饿了么移动技术负责人胡彪于移动性能优化专场发表了题为《浅谈App优化》的演讲,现场分享了饿了么在移动端性能优化方面的踩过的一些坑,以及采坑过程中一点心得。

1.jpg

以下为演讲实录:

胡彪:大家好,我是来自饿了么的胡彪,目前负责移动技术。大会组织委找到我的时候,其实我是拒绝的。因为饿了么既不是行业鼻祖也不是TOP级品牌,如果想讲APM这一块的东西,我是没有很多的自信的。饿了么还是一个创业公司,技术积累不像BAT如此深厚,但既然大会让我过来,我也就好好分享一下。

一、一次惨痛的教训

今天主要给大家讲述一个APP的瘦身过程,还有就是饿了么API Gateway跟大家分享一下,最后还会讲一下Network做的一些优化。先给大家看下图,在座各位有没有一眼看到这个图就觉察到一些异常的地方呢?这是整个中国互联网O2O行业或者任何第三方电商的异常曲线。同时熟悉外卖行业的也知道,这也是外卖曲线,只有在中午10点半到12点,下午4点到6点再到8点,大家可以看到是高峰。那是什么造成这个流量爆增呢?把这个图放大看一下,从这个点开始一直到这里,服务器出口带宽流量爆增高风两倍。这是什么原因造成的?在服务稳定的时候为什么出现这样的情况?

2.jpg

原因是一个开发人员,我们在对APP做发布配制的时候没有做CDN,直接回到源站进行下载,没有通过CDN导致服务器流量增加了2倍。在40分钟的时间里大概浪费了60万人民币流量费。为什么说这样一个案例呢?随着现在无线网还有4G网络的普及,包括流量费不断降低,很多开发人员感觉没有必要去在乎多一兆或者多两兆。但是通过这个案例你会发现可能小小一兆两兆更多是为了你自己。如果你哪一天有一个发布,没有直接回源,放在CDN上面去,同样会面临同样的痛苦,通过这个惨痛的教训告诉我们,APP瘦身利人利己,百利而无一害。

二、App Diet

那么我们要怎么做呢?先来看看下图

3.jpg

今天主要讲一下安卓的东西,我们首先开启需要minify、对资源做shrinkResources、不用这些资源全部删除掉。同时尽量避免使用大图片,尽可能使用png的图片,增加资源的复用率。饿了么有很多款APP,主要的工作是什么样子?类似于OA办公,地推人员商户做一些合作、帮商户开店、帮商户管理一些餐厅、还有管理整个业务模块。用户量不高,不到1万用户,我们内部地推人员在用,但是也是我们内部的一个核心。一旦这个出现问题了,我们跟商户基本上就失联了,今年3月份我接手这个APP之前安卓安装包18兆,iOS包也将近30兆。通过一步一步架构调整,我们现在已经把这个APP包大小减少到6兆,iOS包减少到低于10兆。接下来说一下我们在API gateway做的一些工作和经验。

三、API Gateway

4.jpg

首先放两张图,大家可以看到两张图以后感觉这有什么区别呢?其实是有的。正常情况下,我们开发客户端,通过TCP、通过HTTP、通过各种各样的API,不管是restful,还是其他风格的API所有端都是为了做一些hide access的东西,一些内部业务的逻辑一些保护,只能够去开发一些Service。包括做数据库的业务,都是在Service层面,通过网络层返回给用户而已。其实API这一层承担工作,本身非常非常的少。

因为整个下层,饿了么自主研发一套SOA的框架。目前支持Python,Java语言,下面有很多MySQL Cluster,Redis Cluster,MQ Cluster一系列的Cluster,API Service不应该去做跟业务相关的任何东西。但是,我们往往遇到一个困境,就是不能没有一个专门的Team做API,这会造成了什么情况?最大的问题就是三方的沟通。首先,客户端人员跟API Team沟通,API Team的人和写Service的沟通。所以大家开发过程中遇到一个问题,客户端只需要开发一周,客户服务端需要两三周时间,没有办法联合调整,调了以后很难定位问题。在这种困境之下,我们开发了MUX,它是主要做什么工作呢?

5.jpg

从此以后我们不再有API,通过config调用Service想要访问什么,需要什么数据,客户端需要什么数据,通过简单的config就能取到想要的数据。然后客户端开发人员不再需要跟API开发沟通,也不再有API team,把整个业务层降低了一层。

并且,在一个请求里面可以完成多个不同的业务。比如说一些比较复杂的业务,首页需要请求非常多的一些业务,为了做到这些业务的原子化,可能就会发生很多的请求。一些公司可能在首页做一些wrap把很多的业务数据,banner,item等等一系列的数据融合在很大很大的json或者xml里面。但是这个接口原子性,因为banner更新频度跟item不一样,缓存策略也不一样,在做trouble shooting时候就是非常非常难处理这样的问题。

所以,大家看起来这两个图一模一样的,但实际上我们做了这么多的事情。API team我们以前有10个人,现在解散了。解散是为了把他们的能力发挥到更好的岗位上面去,人力成本就降低了,10个人一年也是几百万研发成本。同时所有东西都是configurable的,是可以自动化配制定义的,所以可能不再需要一些专门的人,只需要一个半熟练工,详细阅读user guide细理解每一个配制意义就可以了。flexiablility也是一个核心的痛点,我们减少了业务复杂度,我们Service更flexiability。Loose coupling刚也是说了,我们这一层API不做任何遍历直到解码,这代表着API不会出错。发现了一些错误时候,第一时间就是找客户端人员,一层一层定位,你肯定找不到DBA这个接口为什么不对,随着我们用config减少了API这一层trouble shooting操作,我们配对了在这一层肯定不会出错,接下来就可以找Service和SOA层面的东西,还有其他的一些DB storage的东西。

最后一点在这里说一下,trouble shooting也是有很多自动化运营的东西,有很多业务曲线在里面。我们可以把这些曲线弄出来以后,很容易找到相应的问题,因为我们的业务业杂度降低了。

四、Network Optimization

今天和昨天讲了很多APM、性能可视化的东西,还有我们这个专场刚刚网易还有上午刘刚老师讲了很多的东西,我想到一点,我们要去hook网络数据,我们要切面获取网络请求、首包时间、DNS一系列的、业务详细时间等。这些数据最终要落到哪里去?最终还是落到服务器上面去,我们做storage的数据流量要远远超过我们的API business logic访问。一个比较大APP开发完以后,有100个接口左右,并且用户在每一个页面停留时间,用户每一个页面操作的频度都很高。我们的DAU跟很多大公司没有办法跟他比。但是我们的DAU都是真的,用户饿了有需求了才打开我们APP,转化率非常高,大概三分之一都转化成真正的订单。

所以,在我们APP里面停留的时间,基本上就是打开,找到想吃的餐厅,下单,支付,整个生命周期就是3分钟5分钟,很难有一个人在APP上面选20分钟完全不知道自己吃什么。但是,我说这个问题是想说,定餐访问10个不到的接口,所有的API数据可能产生10倍,并且这些数据量远远大于API量。这些数据包含首包时间,DNS时间,还有SSH时间等等一系列的时间,还可能做一些HTTP、DNS等,还有页面一些跳转,页面耗电,这些数据都可以归到APM层面,但是我今天要说的并不是APM,听云包括在座的都比我们好,有很多欠缺的地方。

6.jpg

我们退而求其次,如何在网络层做一些优化?上图是我先抛出一个结果,对接下来的演讲有个更直观明了的东西。我传文本大部分数据都是非实时的,PB之后没有什么变化,淡在我做了压缩以后,PB加GZIP的情况下20条数据可以达到88.8%的压缩比,PB加7Z可以达到91.2%,可以看到我发出去的数据就是2K多非常的小。同样把数据放到100条,很多数据也都是非实时的,如果是100条,我们看一下压缩比,PB加GZIP压缩比为91.2%,pb加7Z能达到93.6%。

7.jpg

我们来看看上面一张图,我把整个请求的数据作为一个json,然后变成一个string,同时把string作为PB的一个字段扔回PB里面去,不可能压缩很多。所以,我加了一些头一些版本一些扩展,导致我的PB的文件会比我的纯文本文件还要大。如果我不用json,我直接把数据全PB化,大家猜一猜,最高压缩比达到多少呢?全部用PB的时候,在100条的时候,我最高加到了99.4%。就是说100兆的东西压完以后就是剩下600K。这个压缩比非常非常的惊人。但是为什么我没有用纯PB的方式做呢?因为PB的扩展性非常的差。我现在可能感觉用PB,把数据格式定义非常好,但是以后扩展怎么办?随着不断地扩展,有很多的字段废弃掉,我依然把这些字段放在PB里面去,可能暂时看起来这个数据的确比用纯PB要大一些。

8.jpg

所以,这就是为什么大家可以看到刚刚那个图为什么PB比json大,其实PB本身比json小,一个数据可以压到45%到60%左右,同时要看数据重复性,APM和UBT的数据有很多大的重复性,包括页面一些东西都是重复的,压缩也要高一些。

我们刚刚说的都是如何压缩body,但是大家用HTTP 1.0和1.1都是知道有很多Header组。可以看一下上面的图Header有很大的,我想压缩Header怎么办?要么使用HTTP/2。我们用HTTP/2,不仅可以做到batch-request,还可以做到Header压缩。我用HTTP/2做过试验,没有贴图我大概可以370bytes可以压到大41到45的样子,这个压缩比大概是在90%。

所以我们会用到HTTP/2,同时去尝试更多压缩的算法。什么是压缩算法?我们考虑到了数据量庞大,APM的数据特别是crash一些数据,还有crash整个用户一些log数据可能会非常大。我们可能考虑更好的一些,因为压缩算法大家都是知道的,你是多耗用资源还是少耗用资源多耗用内存?因为手机端特别是安卓,首先碎片化非常非常的严重,在国内各种各样的rom、手机配制也是不一样的,如果我们对于CPU对于内存耗用比较多也是有很多的问题。所以,我们在选取压缩算法的时候,主要考虑更多的是性能问题,而不是纯粹压缩比。如果压到99.9%,对于手机的消耗性能高,造成页面卡顿,手机发烫,发热,耗电非常高,这个也是不可取的。

同时,也是积极地考虑把一部分的业务用上APM,因为APM的东西有一些实时性比较高,包括HTTP的数据也是要求相对比较高一些。用过饿了么的朋友可以感觉到,一个订单一个操作会影响到首页排名,每一次操作都可以影响到一些排名,这个时候用到实时UBT的一些数据,包括实时APM的数据。这样的数据我想做batch request已经不可能了,二次调的压缩数据最高就是达到91.2%。

在这个时候因为本身没有办法做batch-request,其实不管用不用HTTP/2都是没有意义的,这个时候就是考虑用TCP去替换HTTP。

Q&A

Q1:最后说的饿了么例子,具体能讲清楚一些么?按照压缩方式不可以了,最后它本身采取什么方式? 

A:就是udb的数据,比如说user behavior数据和APM的数据大部分都是非实时数据,一般的都不会care之前用户操作的数据,每一个页面耗电损时,页面性能一些问题可能看一个整体的一个曲线,可能看前一天,前几天跟今天的一些对比。对于这样的数据就是非实时数据,可以做batch request。在整个APP打开首页做餐厅选择,跳转等等一系列的10几个页面,做下单等等一系列的操作,产生上百条这样的user behavior数据,同时又产生了若干connection time ,read time, ssl time这样的数据。每一个产生的数据真的有必要非常实时吗?batch request最高的压缩比可以达到99.4%,但是同样有一些数据如果真的需要非常非常的实时,例如饿了么用户的每一次搜索就是立刻影响到下一次餐厅的排名。无论是API,还是什么算法,单论压缩比跟batch request压缩比是没有办法相比的。像HTTP/2,你第一次Header不会被压缩的,它不会去做batch-request,单调数据测下来如果数据重复率不是非常高,最高就是达到75%,75%相当于99.4%这个差距还是很大的。

Q1:饿了么是实时算的?

A:都是有的。有非实时,有实时的,看哪一种业务场景更适合,只有一些类似的搜索,下单等等一系列的东西才会实时地发。

Q2:老师您好,前面说到了 HTTP 2.0优化,这个优化提升多少?优化APP过程当中碰到问题?做了什么修改?

A:目前,在饿了么HTTP2应用比较有限,我说的应用是限与UBT以及APM这一块儿数据的搜集。因为我们目前APM这一块数据是这样一套架构,先通过HTTP或者是HTTPS,把这些数据通过nginx加lua,自动写到nginx log里面去。然后lua做一些serialize和deserialize的事情。然随之而来就是把这个数据送进到flume里面去,flume会把这个数据自动同步到kafka,一些实时数据我们直接从kafka读出来做consumer。如果非实时数据我们落到hbase里面去,后面做一系列的这样一些数据分析。

然后我们为什么要用HTTP2?我刚刚给大家看了,我的body已经不可以压了。我用HTTP压Header有可能压完以后很多我的包还没有Header大,所以我们是需要用到HTTP2两个特性。一个就是Header的compress,另外一个就是batch request。HTTP/2可以在一个连接上做batch request,处理顺序是no order的,可以随机做很多这个方面的优化。

想阅读更多技术文章,请访问听云技术博客,访问听云官方网站感受更多应用性能优化魔力。

关于作者

APMCon2016

驱动应用架构优化与创新

我要评论

评论请先登录,或注册