饿了么移动APP的架构演进

0 引言

时代演进,技术也随之发展。到今天,APP已然成为绝大多数互联网企业用来获取用户的核心渠道。与此同一时候,伴随着业务量的增长,愈来愈大、愈来愈多的APP也在不断地、持续地挑战着每个移动端研发人员的知识深度,而我们的移动端技术人员也在这个不断接受挑战的过程中,成就了今天的移动互联网时代。饿了么移动APP就是这样一个挑战,多用户量、多业务量,在接受着很多其它更挑剔用户的同一时候,默默地、不断地演进着移动端的架构。

1 MVC

我们常说,脱离业务谈架构就是纯粹的刷流氓。饿了么移动APP的发展也是其业务发展的一面镜子。

在饿了么业务发展的早期。移动APP经历从无到有的阶段。为了高速上线抢占市场,传统移动APP开发的MVC架构成了“短平快”思路的首选:


图1 MVC架构

这样的架构以层次结构简单清晰。代码easy开发而被大多数人所接受。

在MVC的体系架构中,Controller层负责整个APP中主要逻辑功能的实现;Model层则负责数据结构的描写叙述以及数据持久化的功能;而View层作为展现层负责渲染整个APP的UI。

分工清晰,简洁明了;而且这样的系统架构在语言框架层就得到了Apple的支持,所以很适用于APP的startup开发。

然后,这样的架构在开发的后期会因为其超高耦和性,从而造就庞大Controller层。而这也是一直被人所诟病。终于的MVC都从Model-View-Controller走向了Massive-View-Controller 的终点。

2 Module Decoupled

“短平快”的MVC架构帮助饿了么移动APP高速抢占了市场。

而随着代码量的不断添加。臃肿的Controller层也在渐露头角。而业务上。饿了么移动APP也从单一APP发展为多APP齐头并进的格局。这时候,假设减少耦合,复用已有模块成了架构的第一要务。

架构中,模块复用的第一要求便是代码的功能组件化。组件化意味着拥有独立功能的代码从系统中进行抽象并剥离,再以“插件”的形式插回原有系统中。这样剥离出来的功能组件,便能够供其它APP进行使用,从而减少系统中模块与模块之间的耦和性;也同一时候提高了APP之间代码的复用性。

饿了么移动对于组件有两种定义:公有组件和业务组件。公有组件指的是封装得比較好的一些SDK。包括一些第三方组件和自己内部使用的组件。如iOS中最著名的网络SDK AFNetworking,Android下OKHttp。都是这类组件的代表。而对于业务组件,则定义为包括了一系列业务功能的总体,比如登录业务组件。注冊业务组件,即为此类组件的典型代表。

对于公有组件,饿了么移动採取了版本号化的管理方式,而这在iOS和Android平台上也早有比較成熟的解决方式。比如,对于iOS平台,CocoaPods基本上成为了代码组件化管理的标配。在Android平台上,Gradle也是非常成熟和稳健的方案。採用以上管理工具的还有一个原因在于,对企业开发而言,代码也是一种商业机密。基于保密性的目的,支持内网搭建私有server成为了必需。以上的管理工具都可以非常好地支持这些操作。

对于业务的组件化。我们採取了业务模块注冊机制的方式来达到解耦合的目的。每一个业务模块对外提供对应的业务接口,同一时候在系统启动的时候向Excalibur系统注冊自己模块的Scheme(Excalibur是饿了么移动用来保存Scheme与模块之间映射的系统,同一时候能依据Scheme进行Class反射返回)。 当其它业务模块对该业务模块有依赖时。从Excalibur系统中获取相关实例,并调用对应接口来实现调用,从而实现了业务模块之间的解耦目的。

而在业务组件,即业务模块的内部,则能够依据不同开发者的偏好,来实现不同的代码架构。如如今讨论得比較火的MVVM, MVP等,都能够在模块内部进行而不影响总体系统架构。

这时候的架构看起来更像是这样:


图2 EMC架构

这样的E(Excalibur)M(Modules)C(Common)架构以高内聚、低耦合为基本的特点。以面向接口编程为出发点。减少了模块与模块之间的联系。

该架构的另外一大优点则在于攻克了不同系统版本号的兼容性问题。这里举iOS平台下的WebView作为样例来进行说明。Apple从iOS8系统開始提供了一套更好的Web支持框架——WebKit。但在iOS7系统下却无法兼容,从而导致Crash。使用此类架构,能够在iOS7系统下仍然注冊使用传统的WebView来渲染网页,而在iOS8及其以上系统注冊WebKit来作为渲染网页的内核。即避免了Apple严格的审核机制。又达到了动态载入的目的。

3 Hybrid

移动APP的开发有两种不同的路线。Native APP和Web APP。

这两种路线的差别类似于PC时代开发应用程序时的C/S架构和 B/S架构。

以上我们谈到的都属于典型的Native APP,即全部的程序都由本地组件渲染完毕。这类APP长处是显而易见的,渲染速度快、用户体验好。缺点同一时候也十分突出:出现了错误一定要等待下一次用户进行APP更新才可以修复。

Web APP的长处恰好就是Native APP的缺点所在,其页面所有採用H5撰写并存放在server端。每次进行页面渲染时都从server请求最新的页面。一旦页面有错误server端进行更新便能立马解决。

只是其弊端也easy窥见:每次页面都须要请求server。造成渲染时等待时间过长。从而导致的用户体验不够完美,而且性能上较Native APP慢了1-2个数量级;与此同一时候还会导致很多其它的用户流量消耗。还有一个缺点则在于,Web APP在移动端上调用本地的硬件设备存在一定的不便。只是这些弊端也都有对应的解决方式,如PhoneGap将网页提前打包在本地以降低网络的请求时间;同一时候也提供一系列的插件来訪问本地的硬件设备。

然而,虽然如此。其渲染速度上还是会略微存在一定的差距。

Hybrid APP则是综合了二者优缺点的解决方式。

饿了么移动对于此二类APP的观点在于,纯粹展示性的模块会更适合使用Web页面来达到渲染的目的;而很多其它的数据操作性、动画渲染性的模块则更适合採用Native的方式。

基于之前的EMC架构,我们将部分模块又一次进行了架构:


图3 Hybrid-EMC架构

Hybrid-EMC架构中。Web作为一个子模块,注冊增加到整个系统中。从而实现让业务上须要高速迭代的模块达到实时更新的效果。

4 React-Native & Hot Patch

经过这些年的业务发展,Hybrid提供的展示界面更新方案也逐渐地无法满足APP更新迭代的须要。

因此越来越多的动态部署的方案被提了出来,比方iOS下的JSPatch, waxPatch。Android下的Dexpose,AndFix, ClassLoader。都是比較成熟Hot Patch动态部署解决方式。

这些方案的思路都是通过下载远程server的代码来动态更新本地的代码行为。

React-Native则属于还有一种动态部署的方案,其核心原理在于通过JavaScript来调用本地组件进行界面的渲染。

而饿了么移动APP发展到今天。各个APP综合用户量已经过亿。因此一个很小的Bug所带来的问题都可能会直接影响到几万人的使用。为了保证APP的稳定性和健壮性,Hot Patch方案也就成了当下最有待解决的问题。

依据80%的用户訪问20%页面这一80/20原则,保证这20%訪问最频繁的页面的稳定性就是保证了80%的APP的稳定性。因此,饿了么移动对于部分訪问最频繁的模块进行了React-Native备份。

当这部分页面出现故障时,APP能够通过server的配置,自己主动切换成React-Native的备份页面。而与此同一时候开发者开发一个小而精的Hot Patch来修复出现的问题。当Hot Patch完毕修补后。再切换回Native APP的原生功能。

这时候的架构看起来会像是这样:


图4 HotPatch-EMC架构

HotPatch-EMC的架构主要目标在于解决移动APP的稳定性问题。通过RN与Native的主备,能够降低系统APP出错带来的失误成本。

5 结语

我们都知道。对于软件project来说,这世上没有银弹。对于架构而言事实上也很的适用。业务的不断更新,带来了饿了么移动APP架构的不断演进。

架构没有真正的好坏之分。仅仅要适用于自己的业务,就是好的架构!

原文链接:http://www.jianshu.com/p/2141fb0dc62c  

原文地址:https://www.cnblogs.com/jzssuanfa/p/7381112.html