组件群管理是什么:如何用自动化治理大规模代码库

这是我们关于某海外音频科技公司如何进行组件群管理,以及如何大规模管理软件的系列文章第一部分。另请参阅第二部分和第三部分。

简而言之,与其每年对基础设施做 10 次大型软件升级,不如在整个代码库中持续完成 10,000 次小型升级。

这正是 Fleet Management 背后的核心理念。本文将其译为“组件群管理”:通过构建能够安全地一次性修改数千个代码库的自动化工具,我们可以持续维护技术基础设施的健康,而不是依赖缓慢、费力的大规模人工迁移。

对于快速增长的工程组织来说,组件群管理的价值在于:用自动化方式完成依赖升级、漏洞修复、代码重构和重新部署,让代码库长期保持健康、安全和可维护。在企业实际落地这类治理能力时,除了底层自动化工具,也需要将目标、需求、开发、测试、发布和知识沉淀等信息串联起来。例如,PingCode 这类智能化研发管理工具,可以帮助团队把研发管理过程自动化、数据化、智能化,让研发链路中的信息更顺畅地流转,为后续治理和持续改进提供更完整的上下文。

更重要的是,把这些底层维护工作从开发者的待办事项中移除,可以让产品团队专注于更有意思、更有价值的问题,而不是把时间花在从 Java 17.0.4 升级到 17.0.5 这类工作上。

更健康、更安全的代码库,更快乐、更高效的工程师。听起来很不错,不是吗?

在组件群管理系列的第一篇文章中,我们将介绍采用“组件群优先”思维意味着什么,以及我们迄今为止从中获得了哪些收益。

组件群管理是什么:如何用自动化治理大规模代码库

大规模代码库如何保持研发速度

自第一款应用推出以来,这家海外音频科技公司几乎一直处于持续增长状态。增长体现在很多方面:用户数量不断增加,内容库的规模和广度持续扩展,从最初的音乐,到后来的播客,再到有声读物;与此同时,参与代码库开发的团队数量也不断上升。

因此,我们的架构必须能够支持大规模、快速的创新和实验,这一点至关重要。

许多小队,更多组件

我们发现,将软件拆分成许多小型组件非常有效。每个团队都可以完全自主地设计、构建和运维这些组件。团队拥有自己的组件,也可以根据需要独立开发和部署。

这是一种相当标准的微服务架构。尽管我们的架构早于“微服务”这个术语出现,但它适用于各种类型的组件,包括移动端功能、数据管道、服务、网站等。

随着业务规模扩大和组织持续发展,我们在生产环境中运行的独立组件数量也随之增长,如今已经达到数千个。

工程师数量与软件组件数量对比:随着时间推移,组件数量的增长速度远远快于工程师数量。

组件群管理是什么:如何用自动化治理大规模代码库

代码库维护:小更新也会积累成大问题

当你需要维护数千个组件时,即便是很小的更新,也会很快变得十分繁琐。

更复杂的迁移更是如此。例如,从 Python 2 升级到 Python 3,或者扩展我们使用的云区域,都需要数百个团队投入大量工程资源,耗时数月甚至数年。

同样,紧急的安全修复或可靠性修复,也需要大量协调工作,才能确保生产环境及时完成补丁修复。

下图展示了一个典型迁移过程。在这个案例中,我们升级了公司的 Java 运行时环境。那还是引入组件群管理之前。总体来看,这次迁移耗时八个月,提交了约 2000 个半自动化拉取请求,并投入了大量工程工作。

缓慢而艰难的跋涉:在组件群管理出现之前,我们通常需要用数月时间完成软件迁移,例如这次 Java 运行时更新。

组件群管理是什么:如何用自动化治理大规模代码库

除了大量消耗开发者时间,这类维护工作也会影响他们的开发体验。它们通常枯燥、乏味、重复性高,正是最应该由自动化系统完成的工作。

组件群管理:从“小队优先”到“组件群优先”

这些洞察促使我们改变对软件的思考方式:不再只考虑如何逐个组件进行变更,而是考虑如何把变更应用到整个组件群。

我们将这种思维方式称为“组件群优先”,而支撑这种思维方式的实践和基础设施,则称为“组件群管理”。

虽然本文主要关注这项工作的技术层面,但值得注意的是,转向组件群优先思维,也意味着工程文化和基础设施团队职责发生了重大变化。

这意味着,任何变更或问题修复,都不再只是服务于某个团队,而是可能影响整个公司的所有代码。反过来,作为组件的所有者和运维者,你也会开始收到一些针对自己组件的变更,而这些变更未必由你亲自发起,也可能在合并和部署之前并未经过你的逐项审查。

如何将“组件群优先”理念应用到基础设施中

接下来,让我们看看,要安全地修改一个包含数千个组件、约 6000 万行代码的组件群,需要做些什么。

整体来看,我们在源代码管理系统中拥有超过 10 亿行代码,其中约 6000 万行被视为生产组件,因此属于组件群管理范围。

以下是我们需要回答的四个关键问题。

1. 如何定位需要修改的代码?

首先,我们需要找到一种方法,确定哪些地方需要变更。

幸运的是,这方面的大部分基础能力已经具备。我们拥有基本的代码搜索能力,并且所有代码和配置都已导入某云数据仓库中,因此可以进行细粒度、灵活的查询。

同样,生产基础设施也已经完成相应埋点,并导入同一数据查询体系中。这让我们能够查询库依赖、部署、容器、安全漏洞,以及许多其他信息。

对于精准定位变更位置来说,这非常强大,也非常实用。

目前,我们正在探索对代码进行语义索引,以实现更细粒度的定位。例如,识别整个代码库中所有 API 调用点。

2. 所有变更对象是否都已纳入版本控制?

接下来,我们需要确保所有需要修改的内容都已纳入版本控制。在我们的场景中,版本控制使用的是 Git。

代码和配置自然已经做到了这一点。但有相当一部分云资源,例如存储桶、服务账号和数据库实例,当时还没有完全纳入 Git 管理。原因是,我们正处于向完全声明式基础设施迁移,或者说回归的中间阶段。

这部分内容以后再详细展开。就本文而言,我们只需要知道:要实现组件群管理,我们必须先完成这项工作。

3. 如何安全完成大规模自动化变更?

随后,我们需要一种机制,能够安全地编写、应用和发布变更。

简而言之,这套机制必须能够识别变更应该应用在哪里。例如,匹配代码库中的某段特定代码;能够将变更应用到代码库中,例如自动代码重构;还要能够验证变更是否有效,例如通过持续集成构建。

最后,这套机制还必须协调这些变更的合并和部署,并持续监控整个过程,确保一旦构建或部署过程中出现故障,就可以安全中止操作。

值得注意的是,大规模自动化代码重构很快就会变得非常复杂。

海勒姆定律指出:“当 API 的用户数量足够多时,无论你在契约中承诺了什么都不重要;系统中所有可观察到的行为,都会被某些用户依赖。”

我们发现,这一观察非常贴切,也确实适用于我们自己。

目前,我们采用多仓库架构,拥有数千个代码库。尽管我们有充分理由相信,即使未来迁移到单体仓库,本文所介绍的实践和工具仍然适用。

无论如何,一旦代码库规模足够庞大,这类专用工具对于安全、高效地进行全局变更都至关重要。类似经验也可以从某大型科技公司关于 C++ 重构的论文中看到。我们在自己最大的代码库中也已经观察到这一点,而这些代码库目前已经拥有约 100 万行代码。

4. 如何让团队信任未经人工审查的自动化变更?

最后,我们希望能够在几小时或几天内完成整个组件群范围内的变更,而且不占用大量开发者时间。

这就要求变更能够自动验证、自动合并和自动部署,不需要人工干预。

虽然我们通常拥有质量较高的自动化测试,但仍然需要提升部分组件的测试覆盖率,并在某些情况下增加基于容器的集成测试。此外,许多组件在部署期间还缺少自动化金丝雀测试。

我们高度依赖自动化测试。绝大多数组件不使用任何形式的手动测试或预发布环境。例外通常是那些必须与合作伙伴进行端到端验证,或存在额外合规要求的组件。

为了进一步确保我们始终可以从 Git 主分支进行部署,我们还为所有组件实施了定期重建和重新部署。

这保证了每个组件每周至少会被重建和重新部署一次,从而降低因代码老化导致构建或部署失败的风险。

组件群管理的结果:代码库已经证明了价值

目前,我们已经能够对超过 80% 的生产组件进行自动化管理,尤其是数据管道和后端服务。

过去三年,我们完成了 100 多次自动化迁移,并每天自动更新组件的外部和内部库依赖。

我们的自动化流程已经生成并合并了超过 30 万次变更,平均每周新增约 7500 次,其中 75% 会自动合并。

更快乐、更高效的开发者

我们估计,这项工作大幅减少了开发者的重复劳动,让他们能够腾出累计数百人年的时间,投入到更有趣、更高价值的工作中。

情感分析也印证了这一点:超过 95% 的开发者认为,组件群管理提升了软件质量。

更安全的代码库

我们的组件群现在也比以前更健康。

例如,组件所使用的内部库、外部库和框架都能够保持在较新的版本。由于我们持续确保每个组件都及时修复漏洞并获得改进,组件群中已知安全漏洞数量和可靠性事件发生率都显著下降。

例如,针对著名的 Log4j 漏洞,我们只用了 9 个小时,就将修复部署到了 80% 的生产后端服务中。之后又花了几天时间,才完成对当时尚未纳入托管服务的全面推广。

几乎立刻就能安心:在合并 Log4j 初始修复之后,部署第一天结束前,80% 的组件都已经完成补丁修复。

组件群管理是什么:如何用自动化治理大规模代码库

更快发布新功能

同样,这也意味着我们可以比以往更快地向开发者提供内部框架的新功能和改进。

例如,我们内部服务框架的新版本,过去需要大约 200 天,才能通过自然更新覆盖 70% 的后端服务。如今,这个时间缩短到不到 7 天。

这意味着,如果你在内部基础设施平台上工作,就可以更快地迭代并发布新功能。

一周,而不是几个月:过去,某个框架更新需要大约 200 天才能覆盖 70% 的组件群;现在只需要大约 7 天。

组件群管理是什么:如何用自动化治理大规模代码库

提升“重铺”能力

最后,我们每周都会对超过 75% 的生产环境进行“重铺”,也就是从源代码重新构建并重新部署。

这可以降低持续构建和部署失败的风险,缓解安全漏洞,并确保组件始终与 Git 中的最新状态保持一致。

组件更多,重铺频率也更高。

组件群管理是什么:如何用自动化治理大规模代码库

组件群管理的未来

虽然我们目前已经取得了不错的进展,但仍然有很多改进空间,也有许多挑战需要克服。

持续采用

我们正在逐步将剩余的长尾组件纳入组件群管理系统。

这些组件通常不是按照我们的技术标准构建的,因此需要更多开发工作才能实现完全托管。此外,我们还需要纳入其他类型的组件。

如上所述,“组件群优先”也是基础设施团队职责的一项重大变化。我们将继续引导各个团队采用组件群优先策略,并以自动、安全的方式将变更部署到整个组件群,直到所有团队都默认采用这种方式。对于这种跨团队、长期推进的工程治理工作,Worktile 这类通用项目协作系统可以用任务、项目、文档、目标、日历、甘特图、工时和审批等能力,帮助团队把采用计划、责任分工和推进节奏管理起来,避免长期治理工作只停留在口头共识中。

更复杂的变更

我们也希望能够处理越来越复杂的全局变更。

目前,我们在管理库依赖、容器依赖,以及进行较简单的配置和代码重构方面,已经积累了丰富经验。

接下来,我们希望逐步提高自己能够有信心推出的变更复杂度,尤其是前文提到的自动合并和自动部署能力。

提高标准化程度

影响全局变更复杂度的一个重要因素,是系统组件之间的相似度。

如果组件使用相同框架和类似代码模式,大规模变更就会容易得多。

因此,我们希望通过为开发者提供更明确的指导,减少软件生态系统的碎片化。例如,明确推荐并支持的框架和库,并帮助现有组件升级到我们期望的软件状态。

过去一年,我们已经将完全使用标准技术栈的组件比例提高了一倍,并计划在未来几年继续扩展技术栈,推动其进一步普及。

改进工具

最后,我们将专注于简化组件群管理工具,并继续推进长期战略,提高面向开发者的平台抽象层级。

我们希望,每一位开发者都能轻松、安全地完成组件群范围内的变更。

文章包含AI辅助创作,作者:guo,如若转载,请注明出处:https://docs.pingcode.com/baike/5243006

(0)
guoguo
免费注册
电话联系

4008001024

微信咨询
微信咨询
返回顶部