Google 為什麼把幾十億行程式碼放在一個庫

程式設計師私房菜發表於2022-12-05

《ACM通訊》有一篇論文《為什麼 Google 要把幾十億行程式碼放在一個庫?》,作者是谷歌基礎設施小組的工程師。作者詳細講述了Google的程式碼為什麼全部放在一個庫裡面。
Google 為什麼把幾十億行程式碼放在一個庫

概述

谷歌最早使用 CVS 進行程式碼管理,1999年改為 Perforce。那時是一臺 Perforce 主機,加上各種快取機。
當時,全公司的程式碼就在一個倉庫裡面,後來一直沿用這種做法。由於規模不斷增長,Perforce 已經無法滿足需求,谷歌就開始使用自己開發的版本管理系統 Piper。
Piper 架設在谷歌自己的分散式資料庫系統(以前叫 Bigtable,現在改名 Spanner)之上,分佈在全世界10個資料中心,保證世界各地的谷歌員工都有良好的訪問速度。
目前,這個程式碼倉庫包含10億個檔案、3500萬次提交記錄,大小為86TB,使用者達到幾萬人。工作日每秒有50萬次請求,高峰時80萬次,大部分來自自動構建和測試系統。
谷歌90%以上的程式碼,放在 Piper 裡面。對於那些開源的、需要外部協作的專案,程式碼放在 Git,主要是 Android 專案和 Chrome 專案。Git 的特點是,所有歷史記錄都會複製到使用者的本地機器,所以不適合大型專案,必須拆分成更小的庫。以 Android 為例,該專案一共包含800多個獨立的倉庫。

Piper 的設計

2.1 結構
整個倉庫採用樹狀結構。每個團隊有自己的目錄。目錄路徑就是程式碼的名稱空間。每個目錄都有負責人(owner),他負責批准該目錄的檔案變動。
2.2 許可權控制
Piper 支援檔案級別的許可權控制。99% 的程式碼對所有使用者可見,只有少部分重要的配置檔案和機密的關鍵業務,設有訪問限制。
如果機密資訊不小心放上了 Piper,檔案可以被快速清除。並且,所有的讀寫都有日誌,管理員能夠查到誰讀過這個檔案。
2.3 工作流
Piper 的工作流(workflow)如下圖。
Google 為什麼把幾十億行程式碼放在一個庫
開發者先建立檔案的本地複製,這叫做”工作區”(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 倉庫,整個過程不需要人工干預。
單一程式碼倉庫的優點
(1)統一的版本
整個公司的程式碼,有統一的版本和路徑,不存在找不到檔案的最新版本這樣的問題。
(2)廣泛的程式碼共享和複用

任何人都可以瀏覽和使用全公司的程式碼,這大大促進了程式碼的共享和複用。
(3)簡化的依賴管理

如果你是庫檔案或者 API 的作者,因為所有人的程式碼都在一個庫裡面,所以很容易找到依賴你的所有下游程式碼。
每當程式碼變動,所有依賴你的程式碼都會自動構建。如果有大量的構建失敗,那麼系統會自動撤銷這次提交。這樣也保證了所有程式碼依賴的都是最新版本,避免依賴不同的版本所導致的衝突。
另外,由於程式碼的邊界很清楚,所以不會發生迴圈依賴。而且,API的作者也很容易發現,別人怎麼使用他的API。

(4)原子性變動

由於每次程式碼變動所導致的影響,都在一個倉庫裡面,所以都屬於原子性的變動。因此,很容易撤銷,或者預先測試它所造成的影響。

為了防止錯誤提交,谷歌引入了”預提交”(即在提交之前,先分析一下依賴它的程式碼是否會構建失敗)。
(5)大規模程式碼析構
單一程式碼倉庫為查詢和分析程式碼,提供了巨大的方便。
Google的靜態分析引擎 Tricorder 定時執行,對程式碼進行分析。比如,C++ 11 標準公佈以後,很容易找到所有需要改進的變數宣告語句,進行效能最佳化。該引擎還對許多錯誤提供"一鍵修正"的功能,同時產出大量的統計資料。

此外,編譯器團隊也會對不同語言的所有程式碼進行分析,找出不合理的程式碼和過時的API。

單一程式碼倉庫的缺點
單一程式碼倉庫的主要缺點是,所有工具都必須自己寫,因為市場上沒有能夠管理這種規模的程式碼倉庫的軟體。
總結

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

作者: 阮一峰        原文地址:

http://www.ruanyifeng.com/blog/2016/07/google-monolithic-source-repository.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31558358/viewspace-2666926/,如需轉載,請註明出處,否則將追究法律責任。

相關文章