1

在公司最近关于mono repo和multi repo的讨论中,学习到了一些新知识,也触发了一些感想。mono repo 顾名思义,就是公司所有的源代码都在同一个代码库里。当然并不一定这么绝对,有的公司可能有若干个大的代码库,例如M公司的Windows, Office或F公司的前端和后端。multi repo则是指每个项目,每个服务都拥有自己单独的的代码库。

当一个公司到达相当规模的的时候,公司最重要的资产--源代码随着体积的膨胀,会带来一系列的工程挑战:

  1. 同步,编译和构建时间可能变得无法忍受。

  2. 保证代码的稳定变的困难。开发人员同步代码后可能无法成功编译或运行

  3. 单一代码库包含不同的编程语言。编译工具的不同使得新建,更改构建过程变的很困难。

让我们先来看一下这个行星上最大的代码库——谷歌的代码库:Why Google Stores Billions of Lines of Code in a Single Repository

谷歌起始于perforce,后来迁移到自行研发的Piper和CitiC,
代码库包含3千五百万commits, 二十亿行代码,85TB的代码
两万五千工程师每天产生一万六千个commit,另外包括两万五千个自动化系统的commit

这是一个极端的例子,但是我们可以看到,首先,85TB的代码远远超过一台开发机的硬盘,必须要支持能够只同步少部分代码并构建。同时还要保证所有的依赖关系必须能够同时处理。例如,更改一部分代码,所有依赖于它的模块必须也要能够正确编译构建。构建系统必须是分布的和高效的。

每两秒一个commit,必须要保证commit的质量。谷歌付出了巨大的人力物力来维护这样一个单一代码库,究竟是为了什么呢?原文的总结如下:
˲ 统一版本控制,代码拥有一个唯一真实的view;
˲ 更容易支持代码共享和重用;
˲ 简化依赖关系管理;
˲ 每一个变化都是,原子的变化;
˲ 更容易的支持大型重构;
˲ 更容易的支持协作跨团队;
˲ 团队边界和代码所有权的转移变得更容易灵活。
˲ 代码结构更清晰,树结构提供隐含团队命名空间便于管理

这一切都很美好,但对于一般公司意味着需要付出巨大的投入。很多系统,比如分布式构建有着很大的技术挑战, 需要极强的依赖分析和缓存构建。

与mono repo对应的是,multirepo,也就是代码库是分散管理的,每个项目,每个服务拥有自己的代码库。这样项目组可以很快的推进,彼此之间的影响会很小。开源项目可以看作是这种方式。成名公司中,Amazon可以说是最成功的例子配合它们松耦合的SOA架构,也取得了巨大的成功。采用这种方式,最大的挑战是代码共享和依赖管理。由于每个代码库自由选择自己所依赖的版本号,一旦试图共享代码,版本之间的冲突变的很难避免。比如 A 依赖于B,C, B,C都依赖于D,但它们依赖于不同版本的D。这时的处理就变得很困难。当然我们可以使用开发工具去检查发现这种情况。但有时当必须需要B或C升级时,额外的沟通成本就不可避免。

如何选择,这是一个问题。在一家难以投入大量人力于构建系统的时候,可能multi repo 在短期内更有助于生产力。但从长期来看,单一, 高效的构建系统和建立专业的团队支持系统是更好的选择。而今天,谷歌开源了Bazel,Twitter开源了Pants,Facebook开源了buck, 在一定程度上降低了门槛。


十六楼的老民工
0 声望0 粉丝