0x00 引言
从iOS及Android操作系统在2007年面世以来,移动端的浪潮以极快的速度席卷了整个世界,并且创造了互联网的一个全新纪元——移动互联网时代。
在这样一个时代演进的过程中,技术的不断进步和创新给移动端的开发者带来了一次又一次的技术挑战。例如:
- 不断增长的日活用户
- 不断刷新的版本分布
- 不断碎片化的机型分布
- 不断碎片化的操作系统分布
其中,不断增长的日活用户,使得微小概率的闪退也会让越来越多的用户收到影响。
而由APP软件版本分布的增加引起的代码上的碎片化加重,则大量增加了功能管理上的复杂性。
另一方面,手机型号的增长以及操作系统版本的增长,也是给移动端开发者造成了不小的困扰,特别是Android操作系统平台,由于其开放性,造成了大量专项的针对性开发与优化,增加了代码管控的难度和复杂度。这也再一次给移动开发者提出了更高的挑战。
面对这样一系列的技术挑战,饿了么开启了移动基础设施的建设工程,以应对未来在移动端上所面临的变化以及更多的挑战。
本文从以下几个方面谈谈饿了么移动基础设施建设的实践:
- 移动端用户体验的分级
- 移动基础设施的概念
- 饿了么移动基础设施的建设实践
0x01 移动端用户体验的分级
如果说智能手机是科技发展的必然产物,那么APP则是移动互联网时代的推动剂。在这样一个以用户体验为王的时代,追求用户极致的体验往往是产品经理们追逐的最高梦想。因此更简化的流程、更炫酷的动画总是成为每次产品更新迭代上的主角,从不会褪去其No.1
的光环。
然而事实上,APP和传统互联网的web时代有着分明且本质的区别,比如用户更新意愿低、存在故障时难修复、视觉要求更高等。因此,在这样一场追求APP用户极致体验的战争中,移动端程序员兄弟们也应该是并肩作战的团队成员之一。因为技术上的用户体验,重要程度其实并不亚于以上的主角。
Level 1 能用
能用
,是使用APP每个用户最基本的诉求。但当我们衷爱的APP在使用过程中遇到了某些特殊异常时,例如内存访问越界,它往往会表现出一种最让我们反感的表象——闪退,移动端工程师们称之为Crash
。
这种让APP完全无法使用的表象,是当前APP用户最为恼火的场景。因此,如何最大限度地降低APP 的Crash率便成为了移动端技术人员们追求的用户体验最高核心。一款无法稳定运行的APP当然无法得到用户的青睐!
Level 2 可用
移动互联网,顾名思义,其也是互联网的一部分。那么既然是互联网,自然无法脱离网络单谈APP,否则我们做出来的,便仅仅只是一款单机软件而已。
可用
,来自为用户提供稳定可靠的服务表述,这是比较容易理解的。设想一下,当我们中午正在选择美食时,却提示网络不可用;又或是页面上的菊花转了一分钟也没有出现想要的菜单,这些都会让我们对这样一款APP产品失望。然而,可用
却又是比较难实现的一个等级。当用户量少、业务简单时,网络的流量并不会对服务器端造成过大的压力;而随着用户量的增长,不同地域、不同运营商、不同网络环境的一点点小的抖动,都会造成用户网络请求的不确定性。
因此,如何最大限度地保障网络数据的稳定性,让我们的APP可用
,是一个每天都在面临的挑战。
Level 3 好用
当我们的APP达成了能用
和可用
的体验后,第三个层次便来到了好用
。
好用
与前两者体验需求的不同之处在于,好用
除了在产品上要求流程简单便捷之外,同时也对更好的动画效果提出了更高的要求;这往往在技术上表现为每秒刷新的FPS
帧率达到一定数值,页面切换无卡顿感,同时APP能在第一时间响应用户的触摸操作等。
好用
是对产品经理以及APP程序员页面性能优化的极致挑战;是一个长期追求并不断努力的终极目标。
0x02 移动基础设施的概念
在以上的用户体验分层概念中,我们可以看到,这种用户体验的上升是不断打怪升级的战役。既然是打怪升级,自然少不了路途上的荆棘和坎坷。在很长的一段时间内,由于缺乏相应的测试和监控的工具,一度让APP端的问题只能通过后端监控来推断。
为了更好地应对这样一系列与APP相关的问题,我们提出了建设移动基础设施的构想。本节先来谈谈什么是移动基础设施。
我们都知道,一款APP的研发流程大致能够总结为:
- 产品提出设计原型,UED设计好视觉效果稿
- 工程师针对设计稿件进行编码、Debug,最后完成开发
- 工程师将开发好的程序进行打包、发布
- APP产品正式上线并发布
而在最近几年,随着iOS和Android的技术进步,又出现了一系列线上热修复的技术,因此在以上的APP研发流程中再添一员HotPatch修复
。
再简单一点,可以归纳为:
- 产品
- 开发
- 发布
- 线上
- 修复
而移动基础设施, Mobile Infrastructure
,我们称之为Minfra
,提供了除产品流程以外的一整套APP研发管控的SaaS服务;涉及开发、发布、线上和修复的整体管控平台。
0x03 饿了么移动基础设施建设的实践
饿了么移动技术团队在面对以上的流程时,搭建了总体的管控平台Grand
,并分别建立了相应的管控模块来进行保障工作。接下来将分模块来谈谈每个流程的具体细节。
持续集成
持续集成是每个互联网公司基本都会部署的一道开胃菜,通过代码仓库的Webhook
操作来自动触发一次编译构造,从而能够快速定位该代码集成是否会导致整个项目的崩溃。这一步,是一项掌控代码
的操作。
对于持续集成的平台搭建来说,业内最常见也最常用的便是Jenkins
。通过简单的job
配置,便能够轻松跑起一款APP的持续集成。这也是该平台在业内能够占领绝大多数市场的原因之一。同时它还具备强大的可扩展性,简便的集群管控能力。这些优点最终让我们选择了Jenkins
。
然而在饿了么,由于APP数量众多,并且随时有可能会有新的APP成员加入进来。于是乎,在这样一种业务场景下,为每一款APP都单独进行一次自定义配置,成为了一种奢望。如何使用一个job
就能让所有的APP都能跑起来,是我们首要解决的问题。
得益于Jenkins
平台的高度可自定义性,我们使用了自己的Python脚本完成了持续集成的管控工作;使用了Grand
平台实现前端状态的监控工作;每款APP使用一个预定义好的配置,来配合脚本内预定义的不同打包行为,最终汇总结果于Grand
平台。
持续集成平台的搭建,让团队合作的代码最终趋于一种稳定状态;完全自定义的脚本代码,让未来静态代码检测分析
、自动化测试平台
的加入成为可能。真正做到了代码的掌控!
Release
我们的代码已经OK,我们的功能已经完备,接下来就是接受千万用户检验的时刻了。
这时候,发布
这个看起来最寻常、最微乎其微的功能服务,却是发挥极大作用的功臣。我们前面提到,由于用户量巨大,99.99%的Crash率也能给成千上万的用户带来困扰;为最大限度地减少这种困扰,一个具备灰度发布
的服务,被赋予了非凡的意义。
通过向特定的手机、特定的城市、甚至特定的人群发送升级提醒,让部分、少量用户升级到新的APP,来观察这部分用户Crash率成为了我们防止大规模Crash最主要的解决方案之一。在灰度的过程中,一旦发现Crash率快速上升,则可通过关闭“发布”渠道来防止事态的进一步上升,让“能用”这一用户体验等级得到掌控。
看到这里,一定有读者会有疑问,对于Android操作系统而言以上方案也许行得通,但对于iOS是否有更加可行的方案?
的确如此,对于iOS平台而言,由于APP Store的存在,往往很难达到灰度控制的目的;事实上,如果有条件的话,可以适当地采用iOS企业版来做灰度。不过这种方案并不被推荐,因为企业版本身并非为该种目的而生,因此我们也并未完全采取这种方案。
另一种iOS的灰度渠道方案,则是在各大越狱社区中进行分发,同样可以绕过某些监管;当然,由于安全性原因,同样也具备一定的风险。因此,如何取舍还是得看读者自己如何衡量。
HotPatch
上文中提到,在我们APP的发布过程中,一般会让部分用户进行升级,通过观察其Crash率来决定是否最终全量该版本。在过去,这部分用户被“牺牲”后,如果其不主动再次升级自身软件版本,阴影将永远笼罩在他们的头顶。然而数据告诉我们,移动APP用户的主动升级率一直处在低位,因此总会有这样一些用户不断被这团阴霾叨扰,最终选择离开了我们。
在这样一种历史情景下催生的HotPatch
技术,就像是救命稻草一样,拯救了一大批这样的APP用户,同时也拯救了在移动端默默奋斗的程序员们。只需要通过HotPatch
服务,有针对性地下发修复bug的Patch包,就能达到降低Crash率的目的,从而能够很好地增加用户的基本体验,难怪该项技术出现后各大厂商都趋之若鹜。
小结
我们通过提供持续集成
、Release
以及HotPatch
三大服务,使用掌控代码、掌控灰度以及掌控闪退的方式,来避免技术原因上造成的闪退,让用户体验的第一维度,这一最基本的诉求得到满足。
对于用户体验的第二维度,在2016年一个很火的词——APM
,让其成为了可能。
APM
在用户体验第二维度的世界里,网络问题其实是最主要的问题;事实上,网络问题归根到底其实也基本就是两个问题:
- 网络延迟
- 网络错误
在没有移动APM基础设施之前,遇上网络问题时,基本只能求助于后端的监控系统。但当用户的请求并未到达我们自身的IDC机房时,诸如运营商劫持、某省网络抖动等,其产生的延迟和错误,大多只能靠经验或者猜想来解决。这时候如果能从APP端的视角来看待其发生的网络情况和问题,那么就能更有针对性地了解其产生症状的根本。
为了达到收集每款APP所有网络请求的目的,我们采用了移动端的AOP
技术,来获取该APP中发生的每个网络请求的时间信息。这些时间主要包括网络协议栈上的首包时间
,DNS时间
, TCP时间
, SSL时间
和请求时间
。当然,我们也同时获取网络层的错误信息,这些信息主要包括HTTP
层的网络错误码,以及网络链路层的错误代号。
分析以上网络数据中的各个时间序列,基本能够了解到用户设备到机房的各项网络时间,从而更方便地确认导致用户网络请求缓慢的原因是来自于网络的延迟,还是来自于后端的响应超时。如果后端的响应超时成为了主因,这时还能勾再通过该请求的唯一标示符去查询后台的监控系统,从而追溯到问题来源的根本,最后有针对性的进行优化和解决。而通过以上的网络错误码,则可以在第一时间内了解到用户端大量发生的网络链路上的问题情况,给服务器端出现的问题提供宝贵的数据支撑。
通过APM
的网络层错误的收集,可以实时发现某个域名主机所发生的问题。这时,如果能同时结合该域名主机的响应时间,再结合后端的监控系统,便能够达到整条网络链路监控打通的目的,让每一次的服务请求都有源可循,真正做到让我们的APP能够持续地可用
。
俗话说的好,没有度量就无法提高;网络监控提供给我们的数据便是我们提升用户体验最好的度量,让我们能够持续不断地提升可用
服务的质量。
0x04 未来
我们的APP能用
,并且可用
,那么如何更进一步让它好用
,便是我们接下来追求的最终目标。我们设想,如果能够实时了解APP用户在使用过程中的各项流畅度体验数值,那么就能够在接下来的版本中有针对性地对相应的功能进行优化;同时,如果能够了解到我们的用户在研发实验室中没有的机型以及操作系统版本上的各项数值,那么也就能够帮助我们的研发人员有针对性地对该机型或者操作系统进行相应地优化,从而提升用户的流程度体验。
而在另一方面,更好的代码质量检查,也是Grand
接下来所需要进行的工作之一。并且,随着我们移动自动化测试平台Stellar
的研发和加入,相信Grand
会在不久地将来,成为综合一键化打包、发布、自动化监控和告警的智能移动基础服务平台!
本文首发CSDN,所以谢绝转载。如需转载烦请简信于我,谢谢!