Google 爲何把幾十億行代碼放在一個庫?

本文原文連接: ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html,若有侵權,則可刪除。

00 前言

《ACM通訊》有一篇論文《爲何 Google 要把幾十億行代碼放在一個庫?》,做者是谷歌基礎設施小組的工程師。做者詳細講述了Google的代碼爲何所有放在一個庫裏面。html

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 總結

單一代碼倉庫,適合提倡透明開放的大型軟件公司,不適合小公司和有大量私密代碼的公司

相關文章
相關標籤/搜索