美团是全球最大的互联网+生活服务平台,为3.2亿活跃用户和500多万的优质商户提供一个链接线上与线下的电子商务服务。秉承“帮你们吃得更好,生活更好”的使命,咱们的业务覆盖了超过200个品类和2800个城区县网络,在餐饮、外卖、酒店旅游、丽人、家庭、休闲娱乐等领域具备领先的市场地位。html
随着各业务的蓬勃发展,大众点评移动研发团队从当初各自为战的“小做坊”已经发展成为能够协同做战的、拥有千人规模的“正规军”。咱们的移动项目架构为了适应业务发展也发生了天翻地覆的变化,这对移动持续集成提出更高的要求,而整个移动研发团队也迎来了新的机遇和挑战。web
当前移动客户端的组件库超过600个,多个移动项目的代码量达到百万行级别,天天有几百次的发版集成需求。保证近千名移动研发人员顺利进行开发和集成,这是咱们部门的重要使命。可是,前进的道路历来都不是平坦的,在通向目标的大道上,咱们还面临着不少问题与挑战,主要包括如下几个方面:数据库
上图仅仅展现了咱们移动项目中一小部分组件间的依赖关系,能够想象一下,这600多个组件之间的依赖关系,就如同一个城市复杂的道路交通网让人眼花缭乱。这种组件间错综复杂的依赖关系也必然会致使两个严重的问题,第一,若是某个业务须要修改代码,极有可能会影响到其它业务,牵一发而动全身,进而会让不少研发同窗工做时战战兢兢,作项目更加畏首畏尾;第二,管理这些组件间繁琐的依赖关系也是一件使人头疼的事情,如今平均每一个组件的依赖数有70多个,最多的甚至达到了270多个,若是依靠人工来维护这些依赖关系,难如登天。编程
移动研发要完成一个完整功能需求,除了代码开发之外,须要经历组件发版、组件集成、打包、测试。若是测试发现Bug须要进行修复,而后再次经历组件发版、组件集成、打包、测试,直到测试经过交付产品。研发同窗在整个过程当中须要手动提交MR、手动升级组件、手动触发打包以及人工实时监控流程的状态,如此研发会被频繁打断来跟踪处理过程的衔接,势必严重影响开发专一度,下降研发生产力。小程序
目前大众点评的iOS项目构建时间,从两年前的20分钟已经增加到如今的60分钟以上,Android项目也从5分钟增加到11分钟,移动项目构建时间的增加,已经严重影响了移动端开发集成的效率。并且随着业务的快速扩张,项目代码还在持续不断的增加。为了适应业务的高速发展,寻求行之有效的方法来加快移动项目的构建速度,已经变得刻不容缓。缓存
评价App的性能质量指标有不少,例如:CPU使用率、内存占用、流量消耗、响应时间、线上Crash率、包体等等。其中线上Crash直接影响着用户体验,当用户使用App时若是发生闪退,他们颇有可能会给出“一星”差评;而包体大小是影响新用户下载App的重要因素,包体过大用户颇有可能会对你的App失去兴趣。所以,下降App线上Crash率以及控制App包体大小是每一个移动研发都要追求的重要目标。安全
项目依赖复杂、研发流程琐碎、构建速度慢、App质量保证是每一个移动项目在团队、业务发展壮大过程当中都会遇到的问题,本文将根据大众点评移动端多年来积累的实践经验,一步步阐述咱们是如何在实战中解决这些问题的。服务器
MCI(Mobile continuous integration)是大众点评移动端团队多年来实践总结出来的一套行之有效的架构体系。它能实际解决移动项目中依赖复杂、研发流程琐碎、构建速度慢的问题,同时接入MCI架构体系的移动项目能真正有效实现App质量的提高。网络
MCI完整架构体系以下图所示:多线程
MCI架构体系包含移动CI平台、流程自动化建设、静态检查体系、日志监控&分析、信息管理配置,另外MCI还采起二进制集成等措施来提高MCI的构建速度。
咱们经过构建移动CI平台,来保证移动研发在项目依赖极其复杂的状况下,也能互不影响完成业务研发集成;其次咱们设计了合理的CI策略,来帮助移动研发人员走出使人望而生畏的依赖关系管理的“泥潭”。
在构建移动CI平台的基础上,咱们对MCI流程进行自动化建设来解决研发流程琐碎问题,从而解放移动研发生产力。
在CI平台保证集成正确性的状况下,咱们经过依赖扁平化以及优化集成方式等措施来提高MCI的构建速度,进一步提高研发效率。
咱们创建一套完整自研的静态检查体系,针对移动项目的特色,MCI上线全方位的静态检查来促进App质量的提高。
咱们对MCI体系的完整流程进行日志落地,方便问题的追溯与排查,同时经过数据分析来进一步优化MCI的流程以及监控移动App项目的健康情况。
最后,为了方便管理接入MCI的移动项目,咱们建设了统一的项目信息管理配置平台。
接下来,咱们将依次详细探讨MCI架构体系是如何一步步创建,进而解决咱们面临的各类问题。
咱们对目前业内流行的CI系统,如:Travis CI、 CircleCI、Jenkins、Gitlab CI调研后,针对移动项目的特色,综合考虑代码安全性、可扩展性及页面可操做性,最终选择基于Gitlab CI搭建移动持续集成平台,固然咱们也使用Jenkins作一些辅助性的工做。MCI体系的CI核心架构以下图所示:
名词解释:
该架构的优点是可扩展性强、可定制、支持并发。首先CI服务器能够任意扩展,除了专用的服务器能够做为CI服务器,普通我的PC机也能够做为CI服务器(缺点是性能比服务器差,任务执行时间较长);其次每一个集成任务的Pipeline是支持可定制的,托管在MCI的集成项目能够根据自身需求定制与之匹配的Pipeline;最后,每一个集成项目的任务执行是可并发的,所以各业务线间能够互不干扰的进行组件代码集成。
一次完整的组件集成流程包含两个阶段:组件库发版和向目标App工程集成。以下图所示:
第一阶段,在平常功能开发完毕后,研发提PR到指定分支,在对代码进行Review、组件库编译及静态检查无误后,自动发版进入组件池中。全部进入组件池中的组件都可以在不一样App项目中复用。
第二阶段,研发根据须要将组件合入指定App工程。组件A自己的正确性已经在第一阶段的组件库发版中验证,第二阶段是检查组件A的改变是否对目标App中原有依赖它的其它组件形成影响。因此首先须要分析组件A被目标App中哪些组件所依赖,目标App工程按照各自的准入标准,对合入的组件库进行编译和静态分析,待检查无误后,最终合入发布分支。
经过组件发版和集成两阶段的CI流程,组件将被正确集成到目标项目中。而对于存在问题的组件则会阻挡在项目以外,所以不会影响其它业务的正常开发和发版集成,各业务研发流程独立可控。
组件的发版和集成可否经过CI检查,取决于组件当前的依赖以及组件自己是否与目标项目兼容。移动研发须要对组件当前依赖有足够的了解才能顺利完成发版集成,为了减少组件依赖管理的复杂度,咱们设计了合理的发版集成策略来帮助移动研发走出繁琐的版本依赖管理的困境。
每一个组件都有本身的依赖项,不一样组件可能会依赖同一个组件,组件向目标项目集成过程当中会面临以下一些问题:
频繁的版本集成冲突会致使业务协同开发集成效率低下,App测试包的不稳定性会给研发追踪问题带来极大的困扰。问题的根源在于目标项目使用每一个组件的依赖项来进行集成。所以咱们经过在集成项目中显示指定组件版本号以及禁止动态依赖的方式,保证了App测试包的稳定性和可靠性,同时也解决了组件版本集成冲突问题。
组件向组件池发版也同样会涉及依赖项的管理,简单粗暴的方法是指定全部依赖项的版本号,这样作的好处是直观明了,但研发须要对不一样版本依赖项的功能有足够的了解。正如组件集成策略中所述,集成项目中每一个组件的版本都是显示指定而且惟一肯定的,组件中指定依赖项的版本号在集成项目中并不起做用。因此咱们在组件发版时采用自动依赖组件池中最新版本的方式。这样设计的好处在于:
当基础组件库的接口和设计发生较大变化时,能够强有力的推进业务层组件作相应适配,保证了在高度解耦的项目架构下保持高度的敏捷性。但这种能力不能滥用,须要根据业务迭代周期合理安排,并作好提早通知动员工做。
研发流程琐碎的主要缘由是研发须要人工参与持续集成中每一步过程,一旦咱们把移动研发从持续集成过程当中解放出来,天然就能提升研发生产力。咱们经过项目集成发布流程自动化以及优化测试包分发来优化MCI流程。
研发流程中的组件发版、组件集成与App打包都是持续集成中的标准化流程,咱们经过流程托管工具来完成这几个步骤的自动衔接,研发同窗只需关注代码开发与Bug修复。
流程托管工具实现方案以下:
不管iOS仍是Android,在发布App包到市场前都须要作一系列处理,例如iOS须要导出ipa包进行备份,保存符号表来解析线上Crash,以及上传ipa包到iTC(iTunes Connect);而Android除了包备份,保存Mapping文件解析线上Crash外,还要发布App包到不一样的渠道,整个打包发布流程更加复杂繁琐。
在没有MCI流程托管之前,每到App发布日,研发同窗就如临大敌守在打包机器前,披荆斩棘,过五关斩六将,直到全部App包被“运送”到指定地点,搞得十分疲惫。如同项目集成流程托管同样,咱们把整个打包发布流程作了全流程托管,无人值守的自动打包发布方式解放了研发同窗,研发同窗不再用每次都披星戴月,早出晚归,跪键盘了(捂脸)。
对于QA和研发而言,上面的场景是否似曾相识。Bug是QA与研发之间沟通的桥梁,但因为缺少统一的包管理和分发,这种模糊的沟通致使难以快速定位和追溯发生问题的包。为了减小QA和研发之间的无效沟通以及优化包分发流程,咱们亟需一个平台来统一管理分发公司内部的App包,因而MCI App应运而生。
MCI App提供以下功能:
将来MCI App还会支持查询项目集成状态以及App发布提醒、问题反馈,整合移动研发全流程。
移动项目在构建过程当中最为耗时的两个步骤分别为组件依赖计算和工程编译。
组件依赖计算
组件依赖计算是根据项目中指定的集成组件计算出全部相关的依赖项以及依赖版本,当项目中集成组件较多的时候,递归计算依赖项以及依赖版本是一件很是耗时的操做,特别是还要处理相关的依赖冲突。
工程编译
工程编译时间是跟项目工程的代码量成正比的,集团业务在快速发展,代码量也在快速的膨胀。
为了提高项目构建速度,咱们经过依赖扁平化的方法来完全去掉组件依赖计算耗时,以及经过优化项目集成方式的手段来减小工程编译时间。
依赖扁平化的核心思想是事先把依赖项以及依赖版本号进行显示指定,这样经过固定依赖项以及依赖版本就完全去掉了组件依赖计算的耗时,极大的提升了项目构建速度。与此同时,依赖扁平化还额外带来了下面的好处:
一般组件代码都是以源码方式集成到目标工程,这种集成方式的最大缺点是编译速度慢,对于上百万行代码的App,若是采用源码集成的方式,工程编译时间将超过40分钟甚至更长,这个时间,显然会使人崩溃。
实际上组件代码还能够经过二进制的方式集成到目标工程:
相比源码方式集成,组件的二进制包都是预先编译好的,在集成过程当中只须要进行连接无需编译,所以二进制集成的方式能够大幅提高项目编译速度。
为了进一步提升二进制集成效率,咱们还作了几件小事:
(1)多线程下载
尽管二进制集成的方式能减小工程编译时间,但二进制包仍是得从远端下载到CI服务器上。咱们修改了默认单线程下载的策略,经过多线程下载二进制包提高下载效率。
(2)二进制包缓存
研发在MCI上触发不一样的集成任务,这些集成任务间除了升级的组件,其它使用的组件二进制包大部分是相同的,所以咱们在CI服务器上对组件二进制包进行缓存以便不一样任务间进行共享,进一步提高项目构建速度。
咱们在MCI中采用二进制集成而且通过一系列优化后,iOS项目工程的编译时间比原来减小60%,Android项目也比原来减小接近50%,极大地提高了项目构建效率。
除了完成平常需求开发,提升代码质量是每一个研发的必修课。若是每一位移动研发在平时开发中能严格遵照移动编程规范与最佳实践,那不少线上问题彻底能够提早避免。事实上仅仅依靠研发自觉性,难以长期有效的执行,咱们须要把这些移动编程规范和最佳实践切实落地成为静态检查强制执行,才能有效的将问题扼杀在摇篮之中。
静态检查最简单的方式是文本匹配,这种方式检查逻辑简单,但存在局限性。好比编写的静态检查代码维护困难,再者文本匹配能力有限对一些复杂逻辑的处理无能为力。现有针对Objective-C和Java的静态分析工具也有很多,常见的有:OCLint、FindBugs、CheckStyle等等,但这些工具定制门槛较高。为了下降静态检查接入成本,咱们自主研发了一个适应MCI需求的静态分析框架--Hades。
Hades的特色:
Hades的核心思想是对源码生成的AST(Abstract Syntax Tree)进行结构化数据的语义表达,在此基础上咱们就能够创建一系列静态分析工具和服务。做为一个静态分析框架,Hades并不局限于Lint工具的制做,咱们也但愿经过这种结构化的语义表达来对代码有更深层次的理解。所以,咱们能够借助文档型数据库(如:CouchDB、MongoDB等)创建项目代码的语义模型数据库,这样咱们可以经过JS的Map-Reduce创建视图从而快速检索咱们须要查找的内容。关于Hades的技术实现原理咱们将在后续的技术Blog中进行详细阐述,敬请期待。
目前MCI已经上线了覆盖代码基本规范、非空特性、多线程最佳实践、资源合法性、启动流程管控、动态行为管控等20多项静态检查,这些静态检查切实有效地促进了App代码质量的提升。
MCI做为大众点评移动端持续集成的重要平台,稳定高效是要达成的第一目标,日志监控是推进MCI走向稳定高效的重要手段。咱们对MCI全流程的日志进行落地,方便问题追溯与排查,如下是部分线上监控项。
经过监控分析MCI流程中每一步的执行时间,咱们能够进行针对性的优化以提升集成速度。
咱们会对异常流程进行监控而且通知流程发起者,同时咱们会对失败次数较多的Job分析缘由。一部分CI环境或者网络问题MCI能够自动解决,而其它因为代码错误引发的异常MCI会引导移动研发进行问题的排查与解决。
咱们对包体总大小、可执行文件以及图片进行全方面的监控,包体变化的趋势一目了然,对于包体的异常变化咱们能够第一时间感知。
除此以外,咱们还对MCI集成成功率、二进制覆盖率等方面作了监控,作到对MCI全流程了然于胸,让MCI稳定高效的运行。
目前MCI平台已经接入公司多个移动项目,为了接入MCI的项目进行统一方便的信息管理,咱们建设了MCI信息管理平台——摩卡(Mocha)。Mocha平台的功能包含项目信息管理、配置静态检查项以及组件发版集成查询。
Mocha平台负责注册接入MCI项目的基本信息,包含项目地址、项目负责人等,同时对各个项目的成员进行权限管理。
MCI支持不一样项目自定义不一样的静态检查项,在Mocha平台上能够完成项目所需静态检查项的定制,同时支持静态检查白名单的配置审核。
Mocha平台支持组件历史发版集成的记录查询,方便问题的排查与追溯。
做为移动集成项目的可视化配置系统,Mocha平台是MCI的一个重要补充。它使得移动项目接入MCI变得简单快捷,将来Mocha平台还会加入更多的配置项。
本文从大众点评移动项目业务复杂度出发,详细介绍了构建稳定高效的移动持续集成系统的思路与最佳实践方案,解决项目依赖复杂所带来的问题,经过依赖扁平化以及二进制集成提高构建速度。在此基础上,经过自研的静态检查基础设施Hades下降静态检查准入的门槛,帮助提高App质量;最后MCI提供的全流程托管能力能显著提升移动研发生产力。
目前MCI为iOS、Android原生代码的项目集成已经提供了至关完善的支持。此外,MCI还支持Picasso项目的持续集成,Picasso是大众点评自研的高性能跨平台动态化框架,专一于横跨iOS、Android、Web、小程序四端的动态化UI构建。固然移动端原生项目的持续集成和动态化项目的持续集成有共通也有不少不一样之处。将来MCI将在移动工程化领域进一步探索,为移动端业务蓬勃发展保驾护航。
智聪,大众点评iOS技术专家,专一于移动工具链开发,对移动持续集成、静态分析平台建设有深入理解和丰富的实践经验。
邢轶,大众点评Android技术专家,专一于移动持续集成、静态分析、静态化等App基础设施建设。
大众点评移动研发中心,Base上海,为美团提供移动端底层基础设施服务,包含网络通讯、移动监控、推送触达、动态化引擎、移动研发工具等。同时团队还承载流量分发、UGC、内容生态、我的中心等业务研发工做,终年虚位以待专一于移动端研发的各路英雄豪杰。欢迎投递简历:dawei.xing#dianping.com。