导语
本文基于重岳在年DevOps国际峰会北京站的分享内容进行总结,希望通过本篇文章介绍近些年来支付宝面向超大业务体量的挑战,在移动端构建弹性动态架构部分做了怎样的实战与思考,期冀能给读者们带来些许帮助。
同时,关于mPaaS五大组件能力,目前已正式开放试用(文末有申请地址),欢迎体验。
支付宝作为国民级应用,当前国内年活跃用户已经超过8.7亿,提供了超过00项以上的服务,而崩溃率始终维持在万分之五以下,而且每天支付宝都上线新的功能和改进。做到今天这样的成绩,并不容易,是经过长时间的实践经验积累下来的。
支付宝的架构演进主要经历了三个阶段,如果用比喻的话,可以分为独木舟、战列舰和航空母舰三个阶段。
1
独木舟时代
支付宝刚推出移动端时,它的结构非常之简单,除了一些工具组件被划分为模块,业务代码都是糅合在一起。刚开始并没有太大问题,但是当我们的研发人员迅速增长时,问题开始变得棘手起来,仅仅举几个例子便可见一斑。
研发同学晚上提交的可以运行的代码,到第二天早上来更新一下就完全不能用,原因是其他不相干团队提交代码覆盖或者污染了自己的代码。
临近发布点的时候,通常是最忙的,但不是忙着赶功能,而是忙着解决合并代码产生的各种问题,不仅浪费时间,还耽误测试同学的宝贵时间。
即使最后勉强发布了,稳定性和性能也是非常糟糕的,因为各个模块只管自己的,没有统一的规范,也缺乏统一的监控。
最令Android开发头痛的是的问题,彼时Google还没有推出multi-dex的方案。
这些严重的问题让我们的产品研发迭代变得无法持续下去,因此我们决定来一次彻底的重构,于是步入了战列舰时代。
战列舰时代
当设计新一代的客户端架构时,我们从三个方向进行思考:团队协作、研发效率、性能与稳定。
团队协作方面,我们希望整个架构分层合理,基础层面,将通用能力下沉,为更多的上层业务服务,避免重复创造轮子;业务层面,各个业务团队能够独立开发管理,不会对不相关的业务造成影响。基于这个初衷,我们形成了下图这样的架构:
整个客户端架构总共分成四层:业务层、服务层、组件层、框架层。
业务层:只需专注于业务逻辑与界面的实现,当需要调用如支付这样的通用能力时,研发同学直接使用下层提供的服务能力,不需自己开发,如此能够保证核心能力有收口,方便监控。
服务层:常用模块,如登录、支付、营销等,它们不仅自己是业务,也向其他业务提供自己的服务,我们将此类模块归类到服务层。
组件层:这一层提供的是客户端通用能力,如安全、网络、多媒体、存储这些,它们提供稳定的接口给上层使用者,同时不断优化自身内部的性能和稳定性,作为客户端的基石,它们至关重要。
框架层:最为关键的部分,包括容器、微应用、服务框架以及Pipeline,客户端的微应用化、启动管理都依赖框架层的运作。
我们将服务层、组件层和框架层合称为mPaaS,即移动端上的PaaS服务。这些PaaS服务可以复用,我们不仅在支付宝里使用它们,也在其他集团应用,如蚂蚁财富、网商银行等中使用。
业务分治
要实现业务分治,最好的方式就在代码上能够进行隔离,大家不必在同一个Codebase中开发,避免代码合并冲突的现象。这个通常在Android上通常可以通过aar的方式来实现,但是可惜的是我们重构的时候aar还没出来,而且即使有aar,也存在打包时间随代码体积增大线性增长的问题。
我们的解决方案借鉴OSGi的概念,将整个客户端以Bundle为单位划分,每个Bundle可以包含自己的代码、页面和资源。读者可能会想,这究竟和aar有什么分别呢?其实区别很大!
首先,Bundle里的代码部分是已编译的dex,当编译apk时,我们只需要合并dex即可,不需要像aar那样将class编译成dex再进行合并,这样大大节省了打包时间;其次,Bundle是可以独立运行于自己的ClassLoader中的,并且我们可以通过壳代理的方式加载Activity等基础组件,使得动态下发业务成为可能;最后,Bundle里还包含微应用、服务和Pipeline相关的配置信息,框架会根据这些信息启动相应的组件。
mPaaS的服务,即Service类似于Spring框架中的Service,它对外提供接口服务,而使用者不需要知道如何初始化服务的实例以及生命周期管理,这些完全由框架来托管。使用者只需要知道目标服务接口类的方法参数即可,调用时通过框架提供的API来获取实例。对于服务的发布者来说,他在自己的bundle中声明接口类以及实现接口类派生的实例类,并注册相关信息到bundle的manifest文件中。这种做法的本质思想是InversionofControl,减少类之间的复杂依赖,避免繁琐的初始化工作。
以依赖接口的方式进行开发,能够解除服务使用者对服务提供者的依赖,在服务提供者尚未完全开发完成时,使用者可以完全以mock的方式来模拟服务,而不需要修改自己的业务代码,当然,前提是双方协商好服务接口的协议。
支付宝中的页面非常多,直接启动Activity或者ViewController对我们来说远远不够,我们选择在它们上面增加MicroApp,即微应用的概念。微应用具备唯一的应用ID,在框架中标识自己的存在。微应用具有统一的入口,根据使用方传入的字典参数来管理Activity或ViewController。这样能够带来很多好处:
只要应用ID和参数协议不变,使用方不需担心目标应用内部重构带来的影响,直接使用Activity或者ViewController类名造成的引用泛滥的问题不复存在。
微应用的ID和字典参数特性,很容易生成URL,从而实现外部应用使用URL跳转应用内页面。
从数据的角度,我们可以按业务维度来统计用户行为数据。
微应用的概念不仅适用于原生页面,同样也适用于H5和小程序。注册为H5或者小程序类型的应用ID,框架会自动将启动过程delegate给H5或者小程序容器,而使用者完全不必关心应用ID对应的应用类型。
综上所述,微应用化和服务接口所赋予的特性极大提高团队间协作效率,各研发小组之间的依赖更加简单,可以各行其道,更