支付宝做为国民级应用,当前全球用户已经超过 10 亿,提供了超过 200 项以上的服务,而崩溃率始终维持在万分之五如下,并且天天支付宝都上线新的功能和改进。作到今天这样的成绩,并不容易,是通过长时间的实践经验积累下来的。 支付宝的架构演进主要经历了三个阶段,若是用比喻的话,能够分为独木舟 、战列舰 和航空母舰 三个阶段。web
支付宝刚推出移动端时,它的结构很是之简单,除了一些工具组件被划分为模块,业务代码都是糅合在一块儿。刚开始并无太大问题,可是当咱们的研发人员迅速增加时,问题开始变得棘手起来,仅仅举几个例子即可见一斑。
团队协做方面,咱们但愿整个架构分层合理,基础层面,将通用能力下沉,为更多的上层业务服务,避免重复创造轮子;业务层面,各个业务团队可以独立开发管理,不会对不相关的业务形成影响。基于这个初衷,咱们造成了下图这样的架构:后端
咱们将服务层、组件层和框架层合称为 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 文件中。这种作法的本质思想是 Inversion of Control,减小类之间的复杂依赖,避免繁琐的初始化工做。以依赖接口的方式进行开发,可以解除服务使用者对服务提供者的依赖,在服务提供者还没有彻底开发完成时,使用者能够彻底以 mock 的方式来模拟服务,而不须要修改本身的业务代码,固然,前提是双方协商好服务接口的协议。并发
支付宝中的页面很是多,直接启动 Activity 或者 ViewController 对咱们来讲远远不够,咱们选择在它们上面增长 MicroApp,即微应用的概念。微应用具有惟一的应用 ID,在框架中标识本身的存在。微应用具备统一的入口,根据使用方传入的字典参数来管理 Activity 或 ViewController。这样可以带来不少好处:框架
只要应用 ID 和参数协议不变,使用方不需担忧目标应用内部重构带来的影响,直接使用 Activity 或者 ViewController 类名形成的引用泛滥的问题不复存在。
微应用的 ID 和字典参数特性,很容易生成 URL,从而实现外部应用使用 URL 跳转应用内页面。
从数据的角度,咱们能够按业务维度来统计用户行为数据。
微应用的概念不只适用于原生页面,一样也适用于 H5 和小程序。注册为 H5 或者小程序类型的应用 ID,框架会自动将启动过程 delegate 给 H5 或者小程序容器,而使用者彻底没必要关心应用 ID 对应的应用类型。
综上所述,微应用化和服务接口所赋予的特性极大提升团队间协做效率,各研发小组之间的依赖更加简单,能够各行其道,更关注于自身服务的打造建设。
咱们一方面在架构上做出重大改变来提升研发效率,另外一方面也在不断的进行性能优化,改善用户体验。咱们主要从三个层面来着手:
框架层面
制定统一开发规范,业务方使用统一的线程池、存储、网络等组件,并按需进行加载,避免没必要要的启动和耗时操做。
引入 Pipeline 机制,业务模块如需在应用启动时进行初始化工做,必须使用 Pipeline。框架依据业务优先级肯定业务初始化实际。
利用 AOP 切面,对经常使用路径进行耗时统计,追踪性能瓶颈。
基础指标
对于经常使用指标,如闪退、ANR、内存、存储、电量、流量等,进行长期追踪。咱们可以明确获悉每一个版本之间这些指标上的差别,并进行采样分析,定位并解决问题。
向下突破
咱们不只仅在应用层面进行优化,同时也向下探索性能提高的可能性。在这方面,咱们也收获颇丰,好比在 Android 上某些系统版本,经过在启动阶段禁用 GC 的方式得到 20%~30% 的启动时间缩减;在 iOS 上,利用系统自己的 Background Fetch 机制提升进程活跃时间,实现应用秒起。
| 航母时代
随着移动支付的不断普及,面对海量的用户和业务需求,高可用、弹性动态成为支付宝客户端更为艰巨的挑战。支付宝做为集支付、金融、生活为一体的服务平台,须要可以快速稳定的发布服务和引入第三方服务,同时对于用户的反馈和诉求必须可以积极迅速的响应。
咱们在研发模式上做出改变以业务快速迭代的要求,业务逐步由原生页面向 Web 混合页面迁移。原有的研发模式可以很好的知足团队协做的要求,可是随着业务规模的不断增大,代码量相应膨胀致使安装包太大,在iOS上一度超过代码段上限,没法经过 AppStore 审核,另外基于集中时间点的迭代发布,一般是一个月发布一个版本,远不能知足业务的更新速度要求。相较于原生应用开发,Web应用的优点很是明显:
只须要一套代码,Web 应用能够在 iOS 和 Android 客户端中运行,可以相对减小人员的投入。
每一个用户平常使用的功能仅仅是支付宝庞大平台中的一小部分,H5 应用能够作到动态下发,所以能够消除冗余的存储,下降包大小。
近些年来 React Native,Weex 等动态渲染引擎在社区很是活跃,但通过小范围的应用以及考虑到 Web 技术的不断发展以及其在业界公认的地位,咱们最终仍是选择 Web 技术做为动态研发模式的基础。
Web 应用迭代摆脱了客户端集中时间点发布的束缚,各业务线迭代计划变得自主可控。
尽管 Web 应用优点明显,但在移动端上的短板也是显而易见的,它提供的用户体验、性能以及能力上的限制与原生应用有至关大的差距。为了弥补这些差距,咱们作了大量的改进,主要在如下几个方面:
先后端分离,咱们将页面资源离线化,这样节省了资源请求消耗的时间,使得页面打开速度提高明显,解决了在网络环境较差下容易出现白屏的问题。同时,数据请求使用 native 网络通道,可优化的空间更大,安全性更高。
差量更新,客户端更新某业务应用版本时,不需下载完整的新版本资源包,而是下载由发布平台根据客户端本地安装版本计算生成的体积更小的差量包,这样不只可以节省带宽和流量,也提高了业务更新的速度。
推拉结合,解决业务最新版本覆盖率的问题,每次发布新版本时,业务可主动触发消息到客户端,客户端收到通知后会更新该业务应用版本。同时,客户端会定时去检查服务端是否有版本发布,这样可以保证版本发布后大多数用户在短期内得到最新的应用。
容错补偿,客户端可能因为网络、安全或者存储权限等缘由,不能使用或者及时得到离线包,这种状况咱们也考虑进来了。咱们在发布离线资源时,发布平台会自动生成对应的在线 URL 并配置到应用信息中,当客户端加载 Web 应用时发现离线包不可用,会马上启用该url加载内容,可以最大程度保证业务可用性。
Android 独立浏览器内核,Android 碎片化的问题自其诞生之初业已存在,并且目前看上去没有得以解决的迹象。不一样系统、不一样厂商中的浏览器内核一样存在差别,这致使层出不穷的兼容性问题令研发同窗头疼不已,这也违背 Web 一统天下的愿景。为了完全解决并掌控这些问题,咱们引入了独立的 UC 浏览器内核并集成在应用中,这样全部的问题都集中到UC团队解决,变得很是可控,根据数据统计,使用 UC 浏览器内核后浏览器相关的闪退和 ANR 有明显的降低。同时,安全上出现的漏洞,咱们能够在第一时间修复并发布,远比厂商升级更有效率。
Web 应用全方位监控,资源加载异常、JS执行异常、白屏、加载耗时等性能数据会被收集上报至后台,能够及时发现异常。
咱们不只自身提供各类各样的服务,也须要引入第三方服务来服务更多的人群,以往咱们只能引入简单的第三方 H5 页面,它们只能使用支付宝提供的少许功能,并且开发人员能力的差别致使用户体验不是很理想。小程序将支付宝的能力全面开放出来,从开发到测试皆有完整的 IDE 等工具链支持,同时 DSL 简单易用,对于第三方来讲,可以快速开发上线一款体验和功能比以往更强大的小程序。
在支付宝,线上风险是每一个研发人员在业务前必须厘清的事情,评估风险,预防风险,监控风险,风险应急处理方案在上线都要准备好。支付宝线上的高可用保障体系由灰度发布、实时监控、诊判定位和容灾恢复四大部分组成。
灰度发布
灰度发布是预防风险的有效手段之一,对于客户端来讲,线下测试的再怎么完备也没法保证在用户环境下一切正常,直接发布至全量用户是很是危险的操做,在支付宝内部属于严重违规。咱们的发布平台提供多种灰度策略,包括白名单灰度、时间窗灰度、百分比灰度、基于机型地域系统等维度的灰度。新版发布前,优先选取活跃用户和问题高发的机型进行灰度,灰度期间发现并修复问题,不断扩大灰度范围,直到闪退率、卡死率等指标符合发布标准后再进行全量的发布。
实时监控
首先,制定各类线上监控指标,包括闪退、卡死、流畅度、流量、内存、存储以及业务不可用埋点等。
其次,上报策略上闪退、卡死、业务不可用埋点等高优先指标实时上报,第一时间发现异常;数据上报使用独立的进程,确保不影响主业务逻辑;当处于业务高峰时期,好比春节红包、双 11 等大型活动时,咱们可以动态调整上报策略以缓解日志服务端的压力。除了自动上传和周期性上传策略外,咱们经过下发诊断指令至客户端去获取平时用不到但驻留在客户端的日志,好比 logcat 日志。
诊判定位
咱们可以根据客户端上报的各类埋点日志,完整描绘出用户的操做路径,根据这些信息,咱们得以尝试重现用户的问题,数据的真实性相对用户提供的信息更加可靠,能减小错误信息产生的干扰。另外,经过诊断指令上传的 logcat 日志,可以更加完整的信息,帮助咱们更清晰的定位问题,所以咱们一般都要求研发同窗在写代码的过程当中可以多输出些有用的信息。
容灾处理
当故障发生时,第一时间要求是可以止血,避免损失扩大,咱们一般会预置开关到业务逻辑当中,当出现业务大面积异常或资损时,后台推送业务开关至客户端中,将业务可以临时屏蔽下线。
客户端在启动阶段发生的死锁、闪退或者主页异常超过必定阈值,会自动清理应用数据,将应用还原至初始状态,可以一部分由于数据异常致使的启动问题。
咱们使用 hotpatch 技术来修复原生代码,一样 hotpatch 自己是个有风险的技术,所以也要经历灰度发布的阶段来逐步验证线上稳定性,一旦发生因 patch 引发的问题,要马上回滚 patch。
| 启航出海
支付宝的移动架构 mPaaS 不只仅在蚂蚁金服内部获得普遍的采用,并且其核心的组件以及背后的研发理念现在已输出包括广发银行、西安银行、华夏银行等众多金融机构,帮助他们打造更具竞争力的移动平台入口。
关于支付宝移动架构如何演进、如何知足业务和用户的需求,这其中还有不少细节和硬货能够跟读者分享,这里因篇幅限制不可以一一叙述,后续会有更多的相关文章更加深刻探讨各方面的话题。
往期阅读
《开篇 | 蚂蚁金服 mPaaS 服务端核心组件体系概述》
《蚂蚁金服 mPaaS 服务端核心组件体系概述:移动 API 网关 MGS》
《蚂蚁金服 mPaaS 服务端核心组件:亿级并发下的移动端到端网络接入架构解析》
《支付宝 App 构建优化解析:经过安装包重排布优化 Android 端启动性能》
《支付宝 App 构建优化解析:Android 包大小极致压缩》
关注咱们公众号,得到第一手 mPaaS 技术实践干货