共计 2318 个字符,预计需要花费 6 分钟才能阅读完成。
本文原文链接:
ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html
,如有侵权,则可删除。
00 前言
《ACM 通信》有一篇论文《为什么 Google 要把几十亿行代码放在一个库?》,作者是谷歌基础设施小组的工程师。作者具体讲述了 Google 的代码为什么全副放在一个库外面。
01 概述
谷歌最早应用 CVS 进行代码治理,1999 年改为 Perforce。那时是一台 Perforce 主机,加上各种缓存机。
过后,全公司的代码就在一个仓库外面,起初始终沿用这种做法。因为规模一直增长,Perforce 曾经无奈满足需要,谷歌就开始应用本人开发的版本管理系统 Piper。
Piper 架设在谷歌本人的分布式数据库系统(以前叫 Bigtable,当初改名 Spanner)之上,散布在全世界 10 个数据中心,保障世界各地的谷歌员工都有良好的访问速度。
目前,这个代码仓库蕴含 10 亿个文件、3500 万次提交记录,大小为 86TB,用户达到几万人。工作日每秒有 50 万次申请,顶峰时 80 万次,大部分来自主动构建和测试零碎。
谷歌 90% 以上的代码,放在 Piper 外面。对于那些开源的、须要内部合作的我的项目,代码放在 Git,次要是 Android 我的项目和 Chrome 我的项目。Git 的特点是,所有历史记录都会复制到用户的本地机器,所以不适宜大型项目,必须拆分成更小的库。以 Android 为例,该我的项目一共蕴含 800 多个独立的仓库。
02 Piper 的设计
2.1 构造
整个仓库采纳树状构造。每个团队有本人的目录。目录门路就是代码的命名空间。每个目录都有负责人(owner),他负责批准该目录的文件变动。
2.2 权限管制
Piper 反对文件级别的权限管制。99% 的代码对所有用户可见,只有少部分重要的配置文件和秘密的要害业务,设有拜访限度。
如果机密信息不小心放上了 Piper,文件能够被疾速革除。并且,所有的读写都有日志,管理员可能查到谁读过这个文件。
2.3 工作流
Piper 的工作流(workflow)如下图。
开发者先创立文件的本地拷贝,这叫做”工作区”(workspace)。实现开发后,工作区的快照共享给其余开发者进行代码评审。只有通过了评审,代码能力合并到地方仓库。
2.4 客户端
大多数开发者通过一个叫做 CitC 的客户端,拜访 Piper。开发者通过 CitC 浏览和同步 Piper 上的文件,然而编辑和批改是在本人工作区,外面只保留有变动的文件(一个工作区个别不超过 10 个文件)。CitC 带有云贮存机制,每个工作区就是云上的一个目录。通过代码评审当前,这些文件才从 Citc 合并进 Piper。
2.5 骨干开发
Google 采纳”骨干开发”(trunk-based development)。代码个别提交到骨干的头部。这样保障了所有用户看到的都是同一份代码的最新版本。
“骨干开发”防止了合并分支时的麻烦。谷歌个别不采纳分支开发,分支只用来公布。大多数时候,公布分支是骨干某个时点的快照。当前的除错和性能加强,都是提交到骨干,必要时 cherry-pick 到公布分支。与骨干长期并行的开发分支,在谷歌极少见。
因为不采纳 ” 分支开发 ”,谷歌引入新性能,个别在代码中应用开关管制。这防止了另起一个分支,也使得通过配置切换性能变得容易,一旦新性能产生故障,很容易切换回旧性能。等到新性能稳固,再彻底删除旧代码。谷歌有相似 A / B 测试的路由算法,评估代码的体现,因为存在配置开关,这种测试很容易实现。
2.6 代码评审
所有代码合并进仓库之前,都必须进行代码评审。大部分评审对所有人凋谢,任何谷歌员工都能够对代码提意见或者提交变动。
代码评审的根据是《Google 代码格调指南》。谷歌有一个叫做 Critique 的工具,能够查看每一行代码的历史演变。
2.7 自动测试
评审实现后,会主动运行测试。通过测试当前,代码就合并进了 Piper 仓库,整个过程不须要人工干预。
03 繁多代码仓库的长处
(1)对立的版本
整个公司的代码,有对立的版本和门路,不存在找不到文件的最新版本这样的问题。
(2)宽泛的代码共享和复用
任何人都能够浏览和应用全公司的代码,这大大促成了代码的共享和复用。
(3)简化的依赖治理
如果你是库文件或者 API 的作者,因为所有人的代码都在一个库外面,所以很容易找到依赖你的所有上游代码。
每当代码变动,所有依赖你的代码都会主动构建。如果有大量的构建失败,那么零碎会主动撤销这次提交。这样也保障了所有代码依赖的都是最新版本,防止依赖不同的版本所导致的抵触。
另外,因为代码的边界很分明,所以不会产生循环依赖。而且,API 的作者也很容易发现,他人怎么应用他的 API。
(4)原子性变动
因为每次代码变动所导致的影响,都在一个仓库外面,所以都属于原子性的变动。因而,很容易撤销,或者事后测试它所造成的影响。
为了避免谬误提交,谷歌引入了”预提交”(即在提交之前,先剖析一下依赖它的代码是否会构建失败)。
(5)大规模代码析构
繁多代码仓库为查找和剖析代码,提供了微小的不便。
Google 的动态剖析引擎 Tricorder 定时运行,对代码进行剖析。比方,C++ 11 规范颁布当前,很容易找到所有须要改良的变量申明语句,进行性能优化。该引擎还对许多谬误提供 ” 一键修改 ” 的性能,同时产出大量的统计数据。
此外,编译器团队也会对不同语言的所有代码进行剖析,找出不合理的代码和过期的 API。
04 繁多代码仓库的毛病
繁多代码仓库的次要毛病是,所有工具都必须本人写,因为市场上没有可能治理这种规模的代码仓库的软件。
05 总结
繁多代码仓库,适宜提倡通明凋谢的大型软件公司,不适宜小公司和有大量私密代码的公司