高可用、弹性动态的金融级移动架构在蚂蚁金服的演进之路

本文涉及的产品
mPaaS订阅基础套餐,标准版 3个月
简介: 支付宝作为国民级应用,当前全球用户已经超过 10 亿,提供了超过 200 项以上的服务,而崩溃率始终维持在万分之五以下,而且每天支付宝都上线新的功能和改进。做到今天这样的成绩,并不容易,是经过长时间的实践经验积累下来的。

| 导语


本文基于重岳在 2018 年 Arch Summit 北京站的分享内容进行总结,希望通过本篇文章介绍近些年来支付宝在移动端架构的上演进和思考,期冀能给读者们带来些许帮助。

支付宝作为国民级应用,当前全球用户已经超过 10 亿,提供了超过 200 项以上的服务,而崩溃率始终维持在万分之五以下,而且每天支付宝都上线新的功能和改进。做到今天这样的成绩,并不容易,是经过长时间的实践经验积累下来的。
支付宝的架构演进主要经历了三个阶段,如果用比喻的话,可以分为独木舟战列舰航空母舰三个阶段。

| 独木舟时代


支付宝刚推出移动端时,它的结构非常之简单,除了一些工具组件被划分为模块,业务代码都是糅合在一起。刚开始并没有太大问题,但是当我们的研发人员迅速增长时,问题开始变得棘手起来,仅仅举几个例子便可见一斑。
  1. 研发同学晚上提交的可以运行的代码,到第二天早上来更新一下就完全不能用,原因是其他不相干团队提交代码覆盖或者污染了自己的代码。
  2. 临近发布点的时候,通常是最忙的,但不是忙着赶功能,而是忙着解决合并代码产生的各种问题,不仅浪费时间,还耽误测试同学的宝贵时间。
  3. 即使最后勉强发布了,稳定性和性能也是非常糟糕的,因为各个模块只管自己的,没有统一的规范,也缺乏统一的监控。
  4. 最令 Android 开发头痛的是 65535 的问题,彼时 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 文件中。这种做法的本质思想是 Inversion of Control,减少类之间的复杂依赖,避免繁琐的初始化工作。以依赖接口的方式进行开发,能够解除服务使用者对服务提供者的依赖,在服务提供者尚未完全开发完成时,使用者可以完全以 mock 的方式来模拟服务,而不需要修改自己的业务代码,当然,前提是双方协商好服务接口的协议。

支付宝中的页面非常多,直接启动 Activity 或者 ViewController 对我们来说远远不够,我们选择在它们上面增加 MicroApp,即微应用的概念。微应用具备唯一的应用 ID,在框架中标识自己的存在。微应用具有统一的入口,根据使用方传入的字典参数来管理 Activity 或 ViewController。这样能够带来很多好处:

  1. 只要应用 ID 和参数协议不变,使用方不需担心目标应用内部重构带来的影响,直接使用 Activity 或者 ViewController 类名造成的引用泛滥的问题不复存在。
  2. 微应用的 ID 和字典参数特性,很容易生成 URL,从而实现外部应用使用 URL 跳转应用内页面。
  3. 从数据的角度,我们可以按业务维度来统计用户行为数据。
  4. 微应用的概念不仅适用于原生页面,同样也适用于 H5 和小程序。注册为 H5 或者小程序类型的应用 ID,框架会自动将启动过程 delegate 给 H5 或者小程序容器,而使用者完全不必关心应用 ID 对应的应用类型。

综上所述,微应用化和服务接口所赋予的特性极大提高团队间协作效率,各研发小组之间的依赖更加简单,可以各行其道,更关注于自身服务的打造建设。

- 性能优化

我们一方面在架构上作出重大改变来提高研发效率,另一方面也在不断的进行性能优化,改善用户体验。我们主要从三个层面来着手:

框架层面

  1. 制定统一开发规范,业务方使用统一的线程池、存储、网络等组件,并按需进行加载,避免不必要的启动和耗时操作。
  2. 引入 Pipeline 机制,业务模块如需在应用启动时进行初始化工作,必须使用 Pipeline。框架依据业务优先级确定业务初始化实际。
  3. 利用 AOP 切面,对常用路径进行耗时统计,追踪性能瓶颈。

基础指标

对于常用指标,如闪退、ANR、内存、存储、电量、流量等,进行长期追踪。我们能够明确获悉每个版本之间这些指标上的差异,并进行采样分析,定位并解决问题。

向下突破

我们不仅仅在应用层面进行优化,同时也向下探索性能提升的可能性。在这方面,我们也收获颇丰,比如在 Android 上某些系统版本,通过在启动阶段禁用 GC 的方式获得 20%~30% 的启动时间缩减;在 iOS 上,利用系统本身的 Background Fetch 机制提高进程活跃时间,实现应用秒起。

| 航母时代

随着移动支付的不断普及,面对海量的用户和业务需求,高可用、弹性动态成为支付宝客户端更为艰巨的挑战。支付宝作为集支付、金融、生活为一体的服务平台,需要能够快速稳定的发布服务和引入第三方服务,同时对于用户的反馈和诉求必须能够积极迅速的响应。

动态研发模式

我们在研发模式上作出改变以业务快速迭代的要求,业务逐步由原生页面向 Web 混合页面迁移。原有的研发模式能够很好的满足团队协作的要求,但是随着业务规模的不断增大,代码量相应膨胀导致安装包太大,在iOS上一度超过代码段上限,无法通过 AppStore 审核,另外基于集中时间点的迭代发布,通常是一个月发布一个版本,远不能满足业务的更新速度要求。相较于原生应用开发,Web应用的优势非常明显:

  1. 只需要一套代码,Web 应用可以在 iOS 和 Android 客户端中运行,能够相对减少人员的投入。
  2. 每个用户日常使用的功能仅仅是支付宝庞大平台中的一小部分,H5 应用可以做到动态下发,因此可以消除冗余的存储,降低包大小。
  3. 近些年来 React Native,Weex 等动态渲染引擎在社区非常活跃,但经过小范围的应用以及考虑到 Web 技术的不断发展以及其在业界公认的地位,我们最终还是选择 Web 技术作为动态研发模式的基础。
  4. Web 应用迭代摆脱了客户端集中时间点发布的束缚,各业务线迭代计划变得自主可控。

打磨 Web 体验

尽管 Web 应用优势明显,但在移动端上的短板也是显而易见的,它提供的用户体验、性能以及能力上的限制与原生应用有相当大的差距。为了弥补这些差距,我们做了大量的改进,主要在以下几个方面:

  1. 前后端分离,我们将页面资源离线化,这样节省了资源请求消耗的时间,使得页面打开速度提升明显,解决了在网络环境较差下容易出现白屏的问题。同时,数据请求使用 native 网络通道,可优化的空间更大,安全性更高。
  2. 差量更新,客户端更新某业务应用版本时,不需下载完整的新版本资源包,而是下载由发布平台根据客户端本地安装版本计算生成的体积更小的差量包,这样不仅能够节省带宽和流量,也提升了业务更新的速度。
  3. 推拉结合,解决业务最新版本覆盖率的问题,每次发布新版本时,业务可主动触发消息到客户端,客户端收到通知后会更新该业务应用版本。同时,客户端会定时去检查服务端是否有版本发布,这样能够保证版本发布后大多数用户在短时间内获得最新的应用。
  4. 容错补偿,客户端可能由于网络、安全或者存储权限等原因,不能使用或者及时获得离线包,这种情况我们也考虑进来了。我们在发布离线资源时,发布平台会自动生成对应的在线 URL 并配置到应用信息中,当客户端加载 Web 应用时发现离线包不可用,会立刻启用该url加载内容,能够最大程度保证业务可用性。
  5. Android 独立浏览器内核,Android 碎片化的问题自其诞生之初业已存在,而且目前看上去没有得以解决的迹象。不同系统、不同厂商中的浏览器内核同样存在差异,这导致层出不穷的兼容性问题令研发同学头疼不已,这也违背 Web 一统天下的愿景。为了彻底解决并掌控这些问题,我们引入了独立的 UC 浏览器内核并集成在应用中,这样所有的问题都集中到UC团队解决,变得非常可控,根据数据统计,使用 UC 浏览器内核后浏览器相关的闪退和 ANR 有明显的下降。同时,安全上出现的漏洞,我们可以在第一时间修复并发布,远比厂商升级更有效率。
  6. Web 应用全方位监控,资源加载异常、JS执行异常、白屏、加载耗时等性能数据会被收集上报至后台,可以及时发现异常。

小程序

我们不仅自身提供各种各样的服务,也需要引入第三方服务来服务更多的人群,以往我们只能引入简单的第三方 H5 页面,它们只能使用支付宝提供的少量功能,而且开发人员能力的差异导致用户体验不是很理想。小程序将支付宝的能力全面开放出来,从开发到测试皆有完整的 IDE 等工具链支持,同时 DSL 简单易用,对于第三方来说,能够快速开发上线一款体验和功能比以往更强大的小程序。

目录
相关文章
|
1月前
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
163 3
Mysql高可用架构方案
|
4月前
|
存储 Cloud Native 关系型数据库
PolarDB 高可用架构设计与实践
【8月更文第27天】 在现代互联网应用中,数据库作为核心的数据存储层,其稳定性和可靠性尤为重要。阿里云的 PolarDB 作为一款云原生的关系型数据库服务,提供了高可用、高性能和自动化的特性,适用于各种规模的应用。本文将详细介绍 PolarDB 的高可用架构设计,并探讨其实现数据安全性和业务连续性的关键技术。
119 0
|
1月前
|
Kubernetes 关系型数据库 MySQL
Kubernetes入门:搭建高可用微服务架构
【10月更文挑战第25天】在快速发展的云计算时代,微服务架构因其灵活性和可扩展性备受青睐。本文通过一个案例分析,展示了如何使用Kubernetes将传统Java Web应用迁移到Kubernetes平台并改造成微服务架构。通过定义Kubernetes服务、创建MySQL的Deployment/RC、改造Web应用以及部署Web应用,最终实现了高可用的微服务架构。Kubernetes不仅提供了服务发现和负载均衡的能力,还通过各种资源管理工具,提升了系统的可扩展性和容错性。
123 3
|
5月前
|
关系型数据库 MySQL Serverless
Serverless高可用架构体验评测
Serverless高可用架构作为企业业务上云不得不考虑的一种低成本高可靠的方案,已经在多领域得到了非常好的验证。希望可以通过阅读文章,让你对Serverless架构得到更深的了解。
12599 21
Serverless高可用架构体验评测
|
4月前
|
运维 监控 关系型数据库
【一文搞懂PGSQL】7. PostgreSQL + repmgr + witness 高可用架构
该文档介绍了如何构建基于PostgreSQL的高可用架构,利用repmgr进行集群管理和故障转移,并引入witness节点增强网络故障检测能力。repmgr是一款轻量级的开源工具,支持一键部署、自动故障转移及分布式节点管理。文档详细描述了环境搭建步骤,包括配置postgresql参数、安装与配置repmgr、注册集群节点以及配置witness节点等。此外,还提供了故障手动与自动切换的方法及常用命令,确保集群稳定运行。
|
4月前
|
数据挖掘 关系型数据库 MySQL
Serverless高可用架构的解决方案体验
Serverless高可用架构的解决方案体验
167 6
|
4月前
|
弹性计算 运维 关系型数据库
云上Serverless高可用架构一键部署体验与测评
在数字化转型背景下,Serverless架构因其实现业务敏捷、降低成本及提升服务可靠性而备受青睐。本文以阿里云Serverless应用引擎(SAE)为核心,展示了一种高可用、低成本且易于扩展的解决方案。通过单地域双可用区部署,构建了具备自动伸缩与故障恢复能力的架构。借助阿里云的一键部署功能,大幅简化了搭建流程,实现了快速部署,并通过性能与成本分析验证了其优势。对比传统ECS,SAE在资源利用与运维效率上表现更佳,特别适合平均负载较低的应用场景。
|
4月前
|
弹性计算 运维 关系型数据库
Serverless高可用架构解决方案评测
Serverless高可用架构方案提供卓越效能与极简运维体验,支持服务托管、弹性伸缩及按量付费,有效降低成本并优化性能。一键部署快速启动,流程直观,文档详实;但在高级配置与特定场景实践方面指导有限。方案采用双可用区部署确保高可用性,自动故障切换保障服务连续。成本模型按需计费,减轻企业负担。功能上集成监控、日志与负载均衡,简化运维,加速上线。性能方面,秒级弹性伸缩保证资源高效匹配负载。总体而言,此方案竞争力强,特别推荐给初创公司及需灵活应对流量波动的场景。
170 2
|
4月前
|
运维 监控 负载均衡
如何构建高可用的系统基础架构
【8月更文挑战第15天】构建高可用的系统基础架构是一个复杂而系统的工程,需要综合考虑设计原则、关键技术和实践策略等多个方面。通过冗余设计、分布式架构、自动化与智能化等技术的运用,可以显著提升系统的可用性和稳定性。同时,加强运维团队的能力建设和制定完善的高可用性策略也是确保系统高可用性的重要保障。希望本文能为读者在构建高可用系统时提供有益的参考和借鉴。
|
4月前
|
关系型数据库 Serverless 分布式数据库
阿里云 Serverless 高可用架构
阿里云的《卓越效能,极简运维,Serverless高可用架构》解决方案提供了全托管服务、自动扩展、高可用性、无缝集成以及内置安全等核心功能。该方案通过免除底层基础设施的管理,允许用户专注于应用程序开发,同时确保应用的稳定运行和资源的有效利用。 **核心功能简介**: - **全托管服务**:用户无需关心底层硬件,由阿里云负责维护和扩展计算资源。 - **自动扩展**:根据业务需求自动调整资源,确保应用在高峰期有足够的计算能力,低谷期则节省成本。 - **高可用性**:多地域和多可用区部署,实现故障自动切换,确保业务连续性。 - **无缝集成**:与阿里云的其他服务(如数据库、消息队列等)深度