一、前言
从本章开始,我们将从支付宝客户端的架构设计入手,对客户端的“容器化框架设计”、“网络优化”、“性能启动优化”、“自动化日志收集”、“RPC”等方面进行分解。组件设计”。 ”、“移动应用监控、诊断、定位”等具体实现将带领您进一步了解支付宝在客户端架构上的迭代和优化过程。
本节将介绍支付宝容器化框架设计的基本思路。
1.1 发展背景
随着应用程序变得更加强大和复杂,以下方面也变得更加强大和复杂:
另外,移动客户端通常需要面对动态开发的挑战;紧急bug修复等运维需求;还有一些线上运营需求,比如动态投放广告、推送访问活动等。如果每次有运维需求都需要客户端发布,那对于传统开发者来说将是一场噩梦。
开发人员深刻理解强大、可靠、可扩展的客户端开发框架的重要性,该框架支持平台级客户端应用程序的大规模并行开发。事实上,面对上述需求和解决困难,客户端框架设计的健壮性和可扩展性往往可以达到事半功倍的效果,尤其是客户端开发者会从中受益匪浅。
那么,作为一个平台级的客户端App,框架应该如何设计,才能满足日新月异的移动互联网时代的困难和需求呢?
1.2 平台级客户端框架面临的问题 序号 问题描述
该项目工程复杂度高,开发、编译、测试和集成难度很大。
支付宝App码200W OK +
平台级应用内部微应用(团队)较多,并行开发要求较高。
内部多达数十个应用程序
APK 大小巨大
支付宝+M导致部分厂家ROM安装失败。
网络版出现各种问题
例如:发布后,五云平台暴露安全漏洞
线上活动运营需求
对于春节红包扫活动,计划是向客户端动态推送新的so文件。
我们可以概括为:平台级客户端框架要解决的就是模块化和动态化两个核心问题。
(本文主要关注模块化相关内容,后续我们会通过其他文章来分析动态能力。)
1.3 框架设计原则
为了解决上述模块化问题,我们必须遵循以下原则来设计客户端框架:
2. 简介
客户端框架是 OSGi(like-as)框架的实现。该术语来自著名的 OSGi 框架的实现。
基于此框架的客户端应用程序是通过构建块逐个构建的。这些构建块称为:。
。引言 3.1 什么是
它是OSGi规范的模块化基本单元,与.os是完全不同的两个概念。
OSGi是指Java应用程序的基本单元。它是一个模块单元(Jar格式),也是上面介绍中提到的构建块。
基于容器框架开发的应用程序也是由众多(APK格式)组成。
本章将详细阐述项目发展三个不同时期的项目形态:
期间形式
发展期
项目
施工期
包
整合期
综合客户基线
3.2 工程
常规项目开发,代码工程通常有两种(两级)类型
项目类型
项目产出
阿尔
应用程序
对于基于容器框架开发的项目,代码项目分为三种(第三级)类型。
项目类型(项目包)(测试包_安装包APK)
项目产出
阿尔
Apk(.jar)
应用程序
关于工程,我们需要了解三件事:
项目结构图请参考:
.3包
如上所述,项目的输出也是一个 APK 文件。
在OSGi规范中,有很多属性。项目输出的 APK 与常规 APK 之间存在一处差异。该插件将为所有属性生成一个特殊文件,并将其放入 APK 中以供容器解释。
除了APK文件之外,项目构建结果还包括:
包文件构建完成后,通常会转到本地/远程mvn仓库,供其他项目参考或者被项目集成。
3.4 基线
前面提到,构建APK实际上就是将很多APK合并成最终APK的过程,而这些很多APK就存放在mvn仓库中。
因此,我们将这些 GAV(,,) 基线称为基线。
当团队/个人开发项目的新功能并经过测试达到可发布状态时,可以更新基线中的版本号。我们将此过程称为基线。我们认为基线中生成的APK是稳定且可运行的;如果没有稳定的项目包,则不应包含在基线中。
基线机制可以很好的隔离模块之间的相互影响,保证不同团队之间开发环境的和谐稳定,达到了我们之前设计的初衷,因此可以很好的支持多个团队的并行开发。
3.5 包属性及配置方法
关于属性,我们可以参考OSGi属性。容器框下定义的属性就简单多了。
下表列出了所有属性和配置方法:
名称 描述 配置方法
-姓名
该名称作为键值存在。同一个客户端apk中,不允许存在同名
插件是根据项目的GAV按照一定的规则生成的。
-
版本号,每个接口包必须向后兼容API版本。
插件根据项目的GAV生成
初始化-
已弃用
只需将其配置为1
-姓名
已弃用
只需将其配置为“”
-姓名
声明于。与-属性相同,是入口类。
由插件根据.xml文件中定义的、、等生成
-ID
项目资源具体技术细节请参见4.2章。
该属性必须由开发商在项目中设置。取值范围为[27, 127]。如果没有资源,则设置为127。如果是依赖树的根节点,则设置为27。
-Dex
这是否包含代码(.dex)
该插件确定文件是否包含 .dex 节点。注意:对于静态链接,由于 .dex 位于主 apk 中,因此该属性将被更正为
-Res
这是否包含资源(.arsc)
插件确定文件是否包含 .arsc 文件。
-
这是否包含so(.so)
是插件根据文件中的so文件来判断的。注意:构建最终的apk时,其中的所有so文件都会包含在apk中,因此该属性将被修正为null。
-
此依赖项列表:格式为 -Name@-。
该属性是插件根据项目工程对其他接口包的依赖情况生成的。
-
导出包(请参考OSGi的导出包概念)。容器将从相应的导出包中加载类。
属性必须由开发人员在项目中设置。例如:非静态连接提供了:com....api.A作为接口供其他用户使用,那么com....api必须配置为导出包。 (使用反射的类也应该包含在导出包中)。有多个导出包,用“,”分隔。出于性能原因,导出包不应有太多设置或太宽泛。
4. 资源管理 4.1 资源管理器
作为开发者,我们知道字符串、布局、图片、动画等资源都可以通过..res获取。目的。
在容器化框架内,原生资源管理无法实现多资源管理。这时我们构建了一个资源管理器来专门处理各种资源的加载和调用,取代原生的资源管理逻辑。 。
然而,由于所有包都是独立编译的,因此它们中的资源很可能具有相同的资源ID。因此,当同一个资源存在时,可能会出现冲突。那么如何解决资源id冲突呢?
4.2 资源ID
作为程序员,我们都知道资源id是一个int值,包含4个字节。它是在构建APK项目时由aapt工具生成的,并在R文件中定义。
示例代码:
public final class R {
public static final class drawable {
public static int xxx_bg=0x1e020000;
}
public static final class id {
public static int xxx_id=0x1e050001;
}
public static final class layout {
public static int xxx_layout=0x1e030000;
}
public static final class string {
public static int xxx_str=0x1e040001;
}
}
这四个字节的含义如下:
如下图:
至此,很多读者应该都明白了,容器框架解决资源ID冲突的方法就是使用修改后的aapt工具打包插件,为每个项目指定不同的,并进行分区隔离,保证不同的资源ID不会冲突。不再重复。这就是为什么需要在项目中指定它。
5. 容器化
关于容器化,由于目前还没有开源,所以本章我们不会涉及源码分析。
上面我们讲了很多话题,所以整个容器化的核心也是如何管理各个。这时候我们的容器管理器就引入了。容器管理器的主要工作是协调各种信息,对各种信息进行增、删、改、查。
应用程序启动后,我们的容器管理器会读取配置信息并生成各个信息实例。
5.1 容器管理器:添加和删除
容器框架的目标是解决客户端App模块化和动态化两个核心问题。添加和删除这两个能力更多的是用来实现动态能力,让容器可以动态地添加和删除每一项。由于本文重点描述模块化能力,因此这一部分我们将单独开一个专题来分析容器的动态能力。
5.2 容器管理器:变化
关于容器管理器的修改能力,我们主要利用修改能力来做一些启动性能优化和模型适配工作。这里涉及到的源码很多,我们就不做过多分析了。
5.3 容器管理器:检查
容器管理器最常用的功能接口应该是查询接口:
通过管理器的查询接口,我们在它们之间进行协调和通信,完成容器化功能。
5.4 组件启动
除了容器管理器之外,另一个重要的点是组件启动器。容器定制类具有本机启动过程,从而自主管理其创建和生命周期。
同时,由于它是我们自己的启动器创建的,所以我们还可以进行一些定制化的改造,以方便它更好地适应容器系统。比如给我们一个定制的资源管理器,管理堆栈并提供外部接口,做每个生命周期的一些方面等等。
定制组件启动器的另一个好处是它们可以动态运行。所谓动态操作是指没有在工厂注册的操作。这个功能更多的是为了支持容器的动态能力。
由于动态操作的实现逻辑涉及到很多核心技术点,所以我们暂时不分析具体实现。
六、总结
通过本节的内容,我们初步了解了端容器化框架的设计思路以及相应的模块。由于篇幅限制,很多技术点我们无法一一展开。
欢迎大家开始体验。关于端容器化框架的设计思路和具体实践,也期待大家的反馈。欢迎大家一起讨论交流。
即日起,填写并提交开发者调查问卷,就有机会获得限量版蚂蚁U型枕。
帮助团队进一步了解您的需求和痛点,以便我们更好地开发和改进产品。我们期待您的反馈。
本次问卷采集截止时间为晚上11.30 18:00,抽奖过程由【 Bus】官方团队全程监督。