支付宝移动端动态化方案实践

帮助咱们更好地优化 mPaaS,获取这次分享 PPT 原稿t.cn/EZVx3bxweb

背景

结合上周分享的《模块化与解耦式开发在蚂蚁金服 mPaaS 深度实践探讨》,咱们已经对支付宝在移动端开发架构的设计思路有了初步了解。本文将结合在 iWeb 武汉站的分享,带领你们进一步了解 mPaaS 在移动端动态化方案设计。小程序

首先,分享内容将分为如下三个方面:api

  1. 支付宝动态化方案的探索;
  2. Nebula 框架浅析;
  3. mPaaS 科技架构与助力

1. 支付宝动态化方案的探索

任何一种技术方案都是在业务的发展和架构的演化中逐渐探索出来的,所以咱们来看一下支付宝架构的演进:浏览器

支付宝架构演进

支付宝从最开始的工具型应用,逐渐发展成平台型应用,一直到如今,已经成为了一个超级 App,它拥有多应用的生态,更加开放和动态化,而且保持着高可用,高性能,高灵敏的强大特性。 随着 App 的逐渐庞大,整个应用的架构也在进行不断的调整,来适应各类特性。如今的支付宝客户端的架构如图所示:安全

总体架构分为五层:容器层、组件层、框架层、服务层、应用层。网络

客户端总体采用统一的框架开发,模块化的开发模式,彻底插件式的容器,支持模块独立发布,方便大规模团队的并行开发。数据结构

在这样的框架结构中,一样包括了咱们的动态化方案。支付宝中的动态化方案主要有两种框架:Nebula小程序架构

支付宝架构演示

这两种方案不只解决了需求迭代速度和发版周期之间的矛盾、跨平台开发、实时发布等一些普适问题,并且有效地保证了发布质量,对线上问题进行紧急止血,同时也有助于创建良好的开放生态。并发

Nebula 是支付宝移动端 Hybrid 解决方案,它提供了良好的外部扩展功能,拥有功能插件化、事件机制、JSApi 定制和 H5App 推送更新管理能力。app

支付宝架构演进

主要功能包括:

  • 接入 H5App 后台,方便管理离线或者在线 H5App,实现 H5 应用的推送、更新。
  • 加载 H5 页面,并按照 Session 的概念进行管理各个页面。
  • Android 使用 UCWebView,拥有解决系统级 Webview Crash 的能力,内存管理更合理,网络加载提高更快,兼容性更好。完全告别了在Android下兼容不一样 Webview 的问题。
  • 支持自定义网络库,自定义网络通道;支持自定义键盘,自定义 Native View替换 H5 标签。
  • 提供丰富的内置 JSAPI,实现譬如页面 push、pop,标题设置等功能;支持用户自定义 JSAPI 和插件功能,扩展业务需求。
  • 自带埋点功能,接入 H5 监控平台,可以实时看到页面加载的性能、错误报警和监控。

还有一种动态化方案就是支付宝小程序

支付宝小程序是一种全新的开发模式,融合了 H5 的易开发性、跨平台性、Native 性能,让开发者能够快速开发高性能的页面,提供优异的用户体验。经过使用支付宝小程序,开发者为支付宝开发了大量优质的小程序,丰富了支付宝生态能力。小程序开放给开发者更多的 JSAPI 和 OpenAPI 能力,经过小程序能够为用户提供多样化便捷服务。

2. Nebula 框架浅析

Nebula 的架构如图所示,从上至下依次为 H5 应用层、服务层、原生框架层

Nebula&小程序

  • H5 应用层:基于 HTML 和 JavaScript 技术开发,在 H5 容器上运行的手机应用,它拥有跨平台的特性,配合离线包的使用能够完成实时热修复的功能。
  • 服务层:为开发者提供了高阶语言的 API 来使用手机系统资源,包括:
    • 视窗系统,开发者可使用它来创造应用 UI,包括文字,图片,按键及定制 View
    • 资源管理,经过它开发者能够方便的访问如多语言文字,图片和布局等非代码资源
    • 应用生命周期管理,它决定应用在手机系统里的开始,结束以及强制关闭的时机
    • H5 容器
  • 原生框架层:是手机系统的基础层,它提供了标准 API 来让高阶语言(好比 Java 和 Object-C)使用底层的硬件,并包含了许多为硬件访问的专有软件库。当上层调用某个框架 API 来访问硬件时,手机系统将加载相应的软件库。

整个 Nebula 框架的核心部分就是 H5 容器,下面看一下 H5 容器的结构:

支付宝架构演进

在容器里面有 H5Service、H5SessionH5Page 这样三个概念

H5ServiceH5SessionH5Page 都是从 H5CoreNode 类扩展而来,以 H5Service 为根节点,它与其余类一同造成了树状结构构成了页面流程和导航。在通常状况下,H5Pages 是 H5Session 的子节点,而 H5Sessions 是 H5Service 的子节点,在任何状况下只有一个 H5Service 根节点存在。

  • H5Service:是 Nebula 里维护 H5 应用全局状态的基础类, 在 H5 应用的生命周期内只有一个 H5Service 的单例全局实例,H5Service 能够进行的操做包括:

    • 建立且打开一个新的 Web activity
    • 建立且开启一个新的 Web page
    • 从共享空间存储和读取数据
    • 注册插件和 Provider
    • 监听应用的生命周期
  • H5Session:一个 H5Session 是由一叠 H5Pages 组成的完整业务流程。例如一个收银台的流程包括:一个购物车的小结页面,一个结帐方式的选择页面,和最后一个结帐确认页面。全部的页面均可以独立存在运做, H5Session 在其中的做用是把这些页面组织起立,按照业务逻辑把它们按序排列来完成业务。当你使用 H5Service 建立且开启一个新的 Web page 时,若是当前没有 H5Session 的话,一个新的 H5Session 实例将被建立,并为后续建立的 Web page 共享。你能够从 H5Session 中移除页面直到页面叠为空,也可使用 H5Session 所提供的方法来获取首页,以及监听该 H5Session 的生命周期。

  • H5Page:是用户看得见,摸得着的页面,也是应用生命周期中最重要的一部分。你能够经过 URL 来加载内容,用 H5Param 来定制页面的外观和行为,甚至能够经过获取 H5Page 的视图层次,把 H5Page 视图和其余原生 UI 部件一块儿内嵌到同一个布局中。

下面是 H5 容器的几个重要组成部分:

  • API 管理器主要管理 JS API:Nebula 中已经提供许多内置的 JS API 供开发者使用,好比操控 UI,显示对话框和 Toast,以及使用网络 RCP 服务等。

  • 插件管理器主要管理 Plugin:若是现有的 JS API 没法知足你的业务需求,你也能够选择创造一个新的插件。你只需把原生代码打包在插件中,在管理器里注册该插件,即可在 Javascript 层使用新的 JS API 了

  • JS Bridge 是链接原生层和 JavaScript 的沟通桥梁:它将 JavaScript 代码转译成能在系统框架运行的字节码,同时也把原生层的数据结构转成 JavaScript 对象使其能在 JavaScript 层处理。这里 Nebula 针对JS Bridge 作了一些优化:

    • 在 Android 里,js 调用 native 的通信是经过 console.log 的方式,这个和其余容器实现不同,其余容器通常经过 prompt 的方式来实现的,可是使用 prompt 的方式,有两个弊端:

      • 使用 prompt 会阻断整个浏览器的进程,若是 native 处理时间一长,会致使页面假死。
      • prompt 是在 UI 层面上会弹出一个模态窗口,在 native 没有对其进行捕获处理的话,会形成一个问题。一旦这个页面放在非此容器的环境下,就会出现一个很诡异的 prompt 弹窗。在支付宝内,曾经出现过这个问题,天猫页面在支付宝 app 里的时候,因为容器机制不一样,页面中 bridge 脚本没有判断环境,致使页面中 js 调用 API 的时候,在页面上出现了 prompt 的模态对话框,严重影响了用户体验,可是若是使用 console.log 的话,就不会出现这个问题。console 的方式避免了不兼容环境的体验问题和同时也避免了页面的假死。
    • jsbridge 注入的时机,因为业务逻辑要依赖 bridge,因此业务的全部逻辑都会在 bridge ready 以后才会触发,而 bridge js 自己运行是要必定的时间的,所以注入的时机对于性能的影响显得很是的重要。但因为 H5 页面的生命周期和容器的生命周期是相互独立的,所以在 H5 生命周期的哪一个阶段注入这段 bridgejs,对于性能的影响就显得异常重要。

    • 如今在支付宝内使用的方式为监听 H5 生活周期的事件,好比说当 Webview 设置 title 结束以后,Android 会放出一个 onReceivedTitle、shouldInterceptRequest 等事件,iOS 会尝试在 webViewDidStartLoad 事件,在监听到这些事件以后,当即注入 bridgejs,让其在 H5 生命周期尽早运行。经过这种方式的注入,通过测试,最先能在页面加载开始后, 50ms 之内就能成功注入 bridgejs。

  • Event 机制:Nebula 提供了一套事件机制来管理事件在 H5Page,H5Session 和 H5Service 之间的流通顺序。一个 H5Event 能够在 H5Page, H5Session 或 H5Service 任何一层发生,事件派遣分为两步完成事件拦截。

这个步骤中事件派遣的顺序为 H5Service -> H5Session or H5Page

事件能够在任何节点被拦截 (若是 interceptEvent() 返回 true ),也能够在任何节点被处理 (若是 handleEvent() 返回 true ):若是事件在派遣过程当中被拦截或处理,该事件将被视为已被消费且再也不继续流通。若是在派遣过程后事件依旧没有被拦截或处理,会有错误抛给呼叫方处理。

仅仅使用传统的 H5 技术展现在线页面,很容易受到网络环境影响,于是下降 H5 页面的性能。

在 Neblua 中咱们使用离线包技术来解决这个问题。离线包是将包括 HTML、Javascript、CSS 等页面内静态资源打包到一个压缩包内,它的目录结构如图所示:

支付宝架构演进

使用离线包可使容器内的 H5 应用具备接近 Native 的体验,主要优点以下::

  • 减小网络环境对 H5 应用的影响:经过下载离线包到本地,而后在客户端打开,把打开H5页面的操做从网络 IO,变成磁盘 IO。直接从本地加载离线包,不只最大程度地摆脱网络环境对 H5 页面的影响,并且加强了用户体验。

  • 提高用户打开 H5 应用的体验:经过离线包的方式把页面内静态资源嵌入到应用中并发布,当用户第一次开启应用的时候,就无需依赖网络环境下载该资源,而是立刻开始使用该应用。

  • 实现动态更新:在推出新版本或是紧急发布的时候,您能够把修改的资源放入离线包,经过更新配置让应用自动下载更新。所以,您无需经过应用商店审核,就能让用户及早接收更新。

下面介绍一下离线包的渲染过程 当 H5 容器发出资源请求时,其访问本地资源或线上资源所使用的 URL 是一致的。H5 容器会先截获该请求,截获请求后,发生以下状况:

  1. 若是本地有资源能够知足该请求的话,H5 容器会使用本地资源。
  2. 若是没有能够知足请求的本地资源,H5 容器会使用线上资源。 所以,不管资源是在本地或者是线上,WebView 都是无感知的。

支付宝架构演进

离线包的下载依赖用户当前的网络。通常状况下,只有在链接 WIFI 的状况下才会在后台下载离线包。若是用户处于移动网络下,不会在后台下载离线包。若是当前用户点击 APP,离线包没有下载好,用户就要等待离线包下载好才能用。

为了解决离线包不可用的场景,fallback 技术应运而生。每一个离线包发布的时候,都会同步在 CDN 发布一个对应的线上版本,目录结构和离线包结构一致。fallback 地址会随离线包信息下发到本地。在离线包没有下载好的场景下,客户端会拦截页面请求,转向对应的 CDN 地址, 实如今线页面和离线页面随时切换。

那么本地资源如何寻址呢,咱们设计了独特的虚拟域名机制,仅对离线应用有效。当页面保存在客户端以后,WebView 若是要访问的话,是经过 file schema 来从本地加载访问的。然而,用户就能在地址栏里直接看到 file 的路径,这就会致使如下问题:

  • 用户体验问题:当用户看到了 file 地址,会对暴露的地址产生不安全感和不自在。
  • 安全性问题:因为 file 协议上直接带上了本地路径,任何用户均可以看到这个文件所在的文件路径,会存在必定的安全隐患。 基于如上问题的考虑,采用虚拟域名的机制而不直接使用 file 路径来访问。虚拟域名是一个符合 URL Scheme 规范的 HTTPS 域名地址,例如 xxxxxxx.h5app.example.com

Nebula 里面的 H5 容器和离线包,在传统的 Hybrid 框架的基础上进行了极致的优化,使整个 H5 应用具备以下特色:

  • 对网络链路强依赖的弱化
  • 加强对设备能力的支持
  • 加强的用户体验

在性能方面,Nebula 在支付宝中通过了亿级用户的考验,crash 和 anr 以及其余稳定性指标有保障。 Android 平台基于 UCWebview 深度定制,crash 率和 anr 量远低于系统webview,拥有解决系统 Webview 问题的能力。 图中展现的就是在 Android 端,UCWebview 和系统 Webview 之间崩溃率和 ANR 率的对比,稳定性的优点显而易见。

支付宝架构演进

最后看一下小程序与 Nebula 支付宝小程序复用 Nebula 容器技术栈,重构了开发方式,对外暴露有限个 jsapi 接口,让 app 开发更简单,更加便捷利用支付宝的能力,进而发布、推广、运营。小程序本质上是也是一个 H5 App 离线包,可是有一些本身的特色。

  • 小程序是为第三方 App 服务的,运行在独立进程,它的稳定和闪退不会影响到主 App,也支持二方 App 运行在主进程。
  • 小程序是支持保活的,极大的提高二次打开的体验。

3. mPaaS 技术架构与助力

Nebula 有这么大优点,如今不只在蚂蚁金服内部使用,也可以提供给外部来使用。

首先什么是 mPaaS 呢,mPaaS 全称是 Mobile Platform as a Service 。是蚂蚁金服首创的移动研发平台,它源于支付宝 App 近 10 年的移动技术实践和思考,为移动开发、测试、运营及运维提供云到端的一站式解决方案,能有效下降技术门槛、减小研发成本、提高开发效率,协助生态伙伴快速搭建稳定高质量的移动 App。

在 mPaaS 中,咱们将 Nebula 的 H5 容器、jsapi 、离线包、小程序这些模块做为一个单独的组件来进行输出,在客户端中进行配置。任何一个 App 经过 mPaaS 插件,添加对应的模块,集成这些功能,只须要这样简单的操做,就可让你的应用具备和支付宝同样强大的动态化能力。

同时 mPaaS 提供的小程序模块,容许用户把运行在支付宝上的小程序,无缝的迁移到本身的 App 中,作到【跨平台跨应用】开发,提升代码的复用能力 Nebula 组件化输出,配合 mPaaS 提供的 MDS (移动发布服务) 来实现动态更新。

mPaaS 提供的 MDS 服务,可以让每次发布更新就像发邮件同样简单。

MDS 具备智能灰度发布的能力,能够经过内部灰度,外部灰度多重验证,保证在正式发布以前,发布的产品质量有充分的保证,同时提供多种升级策略,包括指定人群地域、机型,系统版本,网络环境等多种规则。对于离线包来讲,更新离线包的下载对网络环境要求较高,包的大小越大,更新的成功率越低,在 mPaaS 中,咱们采用增量差分的更新能力,减小数据冗余及设备带宽,在移动网络条件下优点明显。同时保证更新功能的高可用性,升级接口可用率达 99.99%,在线分钟级触达。

下面是 Nebula 的生态基础,首先在集团内部,咱们已经支持了很多产品,同时经过 mPaaS ,咱们也与外部客户合做,将咱们的技术能力输出给他们,典型的几个案例,包括 12306 客户端,广发发现精彩客户端,上海地铁,苏州银行等。

尤为是 12306,使用 mPaaS 改版以后,客户端总体的体验更加优越。12306 整个客户端绝大部分都是使用的 H5 技术,他们就是使用 Nebula H5 容器 配合离线包来实现,不管是页面打开速度,仍是UI事件响应,体验几乎接近 native。在更新发布方面,12306 的 app 包不多更新,以 AppStore 上的发布记录来看,今年只提交了两个版本,基本上都是经过动态化的方式完成业务的迭代发布。

总结下来,蚂蚁金服 mPaaS 中就是经过「Nebula H5容器 + 离线包 + 小程序 + MDS」这样的方式来实现移动端的动态化方案。想要上手体验看看吗?欢迎下载 Android Demo:

  • 注:暂时不支持 iOS 用户扫码下载

关于 mPaaS 移动端动态化的具体实践,若是你有更好的思路或建议,也欢迎一块儿探讨交流。

往期阅读

《开篇 | 模块化与解耦式开发在蚂蚁金服 mPaaS 深度实践探讨》

《口碑 App 各 Bundle 之间的依赖分析指南》

《源码剖析 | 蚂蚁金服 mPaaS 框架下的 RPC 调用历程》

关注咱们公众号,得到第一手 mPaaS 技术实践干货

QRCode