快速的业务发展也对技术支撑提出了更高的要求,架构演进的本质是为了提高研发效率,提高代码稳定性和保证代码质量。架构要解决的问题是如何组织代码。合理的架构设计可以解决大型项目跨团队协作分工和多业务线并行开发的效率问题。
一、抖音工程架构四个阶段的演进过程:
阶段一:抖音原始工程架构
抖音项目一开始是单体架构+Cocoapods,业务代码、工程配置、资源文件全部放在一个大业务仓库,由 Podfile 文件描述第三方仓库的依赖版本。
阶段二:分离壳工程后的工程架构
壳工程包含:工程配置、部分系统资源、工程主入口
业务仓:业务线抽象成独立的Pod
依赖仓:基础能力代码拆分成基础仓库,跟第三方仓库一样独立发版 ,通过Pod管理
优点:
- 一个工程同时支持多个项目。一份代码可以打包出抖音、抖音极速版等项目
- 部分业务线功能复用、部分业务线中台化发展的需求,所有业务线抽象成独立的 Pod,所有业务 Pod 必须通过宿主的壳工程进行集成发版。
- 一些业务线可以通过自动化同步生成自己的子壳工程,实现业务线自己的 Example 工程,进行独立开发,如语音通话,直播,短视频。
缺点:
- 采用 Cocoapods 本身自带的版本依赖决议进行版本分析会消耗大量的时间;
- Podfile.lock 过于繁琐,可读性很差,难以解决 Podfile.lock 的冲突;
- 隐式依赖被动/不符合预期地升级,难以确定性地声明所有依赖,防止隐式依赖被升级;
- 依赖版本在 Podfile/Podfile.lock 重复声明,增加了解决冲突的成本;
- Podfile.lock 参与依赖版本决议流程比较复杂,会出现不符合预期的情况。
阶段三:单仓多组件工程架构
单仓多组件:业务仓支持添加 podspec 增加组件,实现更小粒度的二进制依赖:
- 业务实现层
- 业务接口层
- 服务层和基础层:存放公共的业务逻辑和通用服务,一是满足业务逻辑复用,二是满足子壳工程最小化二进制依赖
都是通过Pod集成方式发版
阶段四:Example 子壳工程架构
子壳工程架构:壳工程支持添加 podspec 增加组件,增加 AWELaunchKit为子壳工程提供运行时的基础能力,满足代码复用和更小二进制依赖
AWELaunchKit:
- 为宿主和其他子壳工程提供了基础服务的依赖和初始化配置,同时提供了一套启动加载的 BootTasks 管理框架,部分业务涉及启动相关的逻辑可以在业务仓对应的服务层中实现,并通过 BootTasks 管理框架注册到启动加载器里面。
- 提供了一套宿主 UI 入口和自定义入口框架。为了方便测试和调试,也整合了整套测试调试框架
组件依赖分析后台
组件化遇到的问题:
1.二进制污染
组件之间的依赖除了显式的依赖,还存在很多隐式依赖,代码层面,除了普通的接口依赖,还有宏依赖、枚举依赖、全局变量依赖以及内联函数等的依赖。单仓 lint 进行编译链接完备性检查并不能解决依赖变动对其他二进制的影响。
2.编译优化
编译优化最高效的方式就是提高缓存的利用率。对于本地研发和 CI 流程,都涉及分布式编译缓存同步。同时通过编译参数优化、依赖优化、hmap 优化也能不同程度的提高编译效率
3.主干分支稳定性问题
对于多业务线并行开发,几百号人的业务开发团队,如果主干分支一旦出现问题,那么解决问题的时间就需要乘上几百倍。因此,需要从编译层面和运行层面都要有足够的机制去保证一个稳定的主干分支,才能保证业务侧的长期稳定性。
4.业务层的依赖耦合问题
大型项目动则千万行的代码,代码间的依赖关系是复杂的网状关系。需要基于代码的语法树模型,从语义中去分析不合理的依赖,并输出治理的方案。
总结
大型项目的组件化工作是一个系统性工程。涉及工程架构的改造、CI/CD 研发工具链的支撑、本地研发工具链的支撑,业务架构的设计优化,需要从各个方面综合考虑成本和收益。
没有最好的架构,只有更好的架构,在架构演进的过程中,我们需要充分考虑架构的改动对业务的影响以及能给业务带来的收益。好的架构一定是能帮助业务节省时间,保证质量的。与此同时,我们在架构改进的过程中,要保证不能影响业务的正常迭代,所以向前兼容且避免大面积冲突也是很重要的事情。
组件化里面处处都有惊喜,比如一个小小的 hmap 优化,可以很大程度的减少编译耗时,比如一个二进制的压缩和解压的优化,可以很大程度减少 pod install 的整体耗时。
当然这里面也会有很多很棘手的问题,需要通过一些特殊的方案解决,比如针对分布式开发,由于阻塞式发版必然会导致一些不同分支存在冲突的代码发版后影响主干的稳定性。
- 本文作者: Grx
- 本文链接: https://ruixiaoguo.github.io/Grx.github.io/Grx.github.io/2021/12/30/抖音工程架构演进/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!