《ACM通信》有一篇論文《為什么 Google 要把幾十億行代碼放在一個(gè)庫(kù)?》豫尽,作者是谷歌基礎(chǔ)設(shè)施小組的工程師篙梢。作者詳細(xì)講述了Google的代碼為什么全部放在一個(gè)庫(kù)里面。
一美旧、概述
谷歌最早使用 CVS 進(jìn)行代碼管理渤滞,1999年改為 Perforce贬墩。那時(shí)是一臺(tái) Perforce 主機(jī),加上各種緩存機(jī)妄呕。
當(dāng)時(shí)陶舞,全公司的代碼就在一個(gè)倉(cāng)庫(kù)里面,后來(lái)一直沿用這種做法绪励。由于規(guī)模不斷增長(zhǎng)肿孵,Perforce 已經(jīng)無(wú)法滿(mǎn)足需求,谷歌就開(kāi)始使用自己開(kāi)發(fā)的版本管理系統(tǒng) Piper。
Piper 架設(shè)在谷歌自己的分布式數(shù)據(jù)庫(kù)系統(tǒng)(以前叫 Bigtable,現(xiàn)在改名 Spanner)之上竖独,分布在全世界10個(gè)數(shù)據(jù)中心矾屯,保證世界各地的谷歌員工都有良好的訪(fǎng)問(wèn)速度。
目前蚯涮,這個(gè)代碼倉(cāng)庫(kù)包含10億個(gè)文件、3500萬(wàn)次提交記錄,大小為86TB眉抬,用戶(hù)達(dá)到幾萬(wàn)人。工作日每秒有50萬(wàn)次請(qǐng)求懈凹,高峰時(shí)80萬(wàn)次蜀变,大部分來(lái)自自動(dòng)構(gòu)建和測(cè)試系統(tǒng)。
谷歌90%以上的代碼介评,放在 Piper 里面库北。對(duì)于那些開(kāi)源的、需要外部協(xié)作的項(xiàng)目们陆,代碼放在 Git寒瓦,主要是 Android 項(xiàng)目和 Chrome 項(xiàng)目。Git 的特點(diǎn)是坪仇,所有歷史記錄都會(huì)復(fù)制到用戶(hù)的本地機(jī)器杂腰,所以不適合大型項(xiàng)目,必須拆分成更小的庫(kù)椅文。以 Android 為例喂很,該項(xiàng)目一共包含800多個(gè)獨(dú)立的倉(cāng)庫(kù)。
二皆刺、Piper 的設(shè)計(jì)
2.1 結(jié)構(gòu)
整個(gè)倉(cāng)庫(kù)采用樹(shù)狀結(jié)構(gòu)少辣。每個(gè)團(tuán)隊(duì)有自己的目錄。目錄路徑就是代碼的命名空間羡蛾。每個(gè)目錄都有負(fù)責(zé)人(owner)漓帅,他負(fù)責(zé)批準(zhǔn)該目錄的文件變動(dòng)。
2.2 權(quán)限控制
Piper 支持文件級(jí)別的權(quán)限控制。99% 的代碼對(duì)所有用戶(hù)可見(jiàn)忙干,只有少部分重要的配置文件和機(jī)密的關(guān)鍵業(yè)務(wù)屯伞,設(shè)有訪(fǎng)問(wèn)限制。
如果機(jī)密信息不小心放上了 Piper豪直,文件可以被快速清除劣摇。并且,所有的讀寫(xiě)都有日志弓乙,管理員能夠查到誰(shuí)讀過(guò)這個(gè)文件末融。
2.3 工作流
Piper 的工作流(workflow)如下圖。
開(kāi)發(fā)者先創(chuàng)建文件的本地拷貝暇韧,這叫做”工作區(qū)”(workspace)勾习。完成開(kāi)發(fā)后,工作區(qū)的快照共享給其他開(kāi)發(fā)者進(jìn)行代碼評(píng)審懈玻。只有通過(guò)了評(píng)審巧婶,代碼才能合并到中央倉(cāng)庫(kù)。
2.4 客戶(hù)端
大多數(shù)開(kāi)發(fā)者通過(guò)一個(gè)叫做 CitC 的客戶(hù)端涂乌,訪(fǎng)問(wèn) Piper艺栈。開(kāi)發(fā)者通過(guò) CitC 瀏覽和同步 Piper 上的文件,但是編輯和修改是在自己工作區(qū)湾盒,里面只保存有變動(dòng)的文件(一個(gè)工作區(qū)一般不超過(guò)10個(gè)文件)湿右。CitC 帶有云儲(chǔ)存機(jī)制,每個(gè)工作區(qū)就是云上的一個(gè)目錄罚勾。通過(guò)代碼評(píng)審以后毅人,這些文件才從 Citc 合并進(jìn) Piper。
2.5 主干開(kāi)發(fā)
Google 采用”主干開(kāi)發(fā)”(trunk-based development)尖殃。代碼一般提交到主干的頭部丈莺。這樣保證了所有用戶(hù)看到的都是同一份代碼的最新版本。
“主干開(kāi)發(fā)”避免了合并分支時(shí)的麻煩送丰。谷歌一般不采用分支開(kāi)發(fā)缔俄,分支只用來(lái)發(fā)布。大多數(shù)時(shí)候蚪战,發(fā)布分支是主干某個(gè)時(shí)點(diǎn)的快照牵现。以后的除錯(cuò)和功能增強(qiáng),都是提交到主干邀桑,必要時(shí) cherry-pick 到發(fā)布分支。與主干長(zhǎng)期并行的開(kāi)發(fā)分支科乎,在谷歌極少見(jiàn)壁畸。
由于不采用"分支開(kāi)發(fā)",谷歌引入新功能,一般在代碼中使用開(kāi)關(guān)控制捏萍。這避免了另起一個(gè)分支太抓,也使得通過(guò)配置切換功能變得容易,一旦新功能發(fā)生故障令杈,很容易切換回舊功能走敌。等到新功能穩(wěn)定,再?gòu)氐讋h除舊代碼逗噩。谷歌有類(lèi)似A/B測(cè)試的路由算法掉丽,評(píng)估代碼的表現(xiàn),由于存在配置開(kāi)關(guān)异雁,這種測(cè)試很容易實(shí)現(xiàn)捶障。
2.6 代碼評(píng)審
所有代碼合并進(jìn)倉(cāng)庫(kù)之前,都必須進(jìn)行代碼評(píng)審纲刀。大部分評(píng)審對(duì)所有人開(kāi)放项炼,任何谷歌員工都可以對(duì)代碼提意見(jiàn)或者提交變動(dòng)。
代碼評(píng)審的依據(jù)是《Google 代碼風(fēng)格指南》示绊。谷歌有一個(gè)叫做 Critique 的工具锭部,可以查看每一行代碼的歷史演變。
2.7 自動(dòng)測(cè)試
評(píng)審?fù)瓿珊竺婧郑瑫?huì)自動(dòng)運(yùn)行測(cè)試空免。通過(guò)測(cè)試以后,代碼就合并進(jìn)了 Piper 倉(cāng)庫(kù)盆耽,整個(gè)過(guò)程不需要人工干預(yù)蹋砚。
三、單一代碼倉(cāng)庫(kù)的優(yōu)點(diǎn)
(1)統(tǒng)一的版本
整個(gè)公司的代碼摄杂,有統(tǒng)一的版本和路徑坝咐,不存在找不到文件的最新版本這樣的問(wèn)題。
(2)廣泛的代碼共享和復(fù)用
任何人都可以瀏覽和使用全公司的代碼析恢,這大大促進(jìn)了代碼的共享和復(fù)用墨坚。
(3)簡(jiǎn)化的依賴(lài)管理
如果你是庫(kù)文件或者 API 的作者,因?yàn)樗腥说拇a都在一個(gè)庫(kù)里面映挂,所以很容易找到依賴(lài)你的所有下游代碼泽篮。
每當(dāng)代碼變動(dòng),所有依賴(lài)你的代碼都會(huì)自動(dòng)構(gòu)建柑船。如果有大量的構(gòu)建失敗帽撑,那么系統(tǒng)會(huì)自動(dòng)撤銷(xiāo)這次提交。這樣也保證了所有代碼依賴(lài)的都是最新版本鞍时,避免依賴(lài)不同的版本所導(dǎo)致的沖突亏拉。
另外扣蜻,由于代碼的邊界很清楚,所以不會(huì)發(fā)生循環(huán)依賴(lài)及塘。而且莽使,API的作者也很容易發(fā)現(xiàn),別人怎么使用他的API笙僚。
(4)原子性變動(dòng)
由于每次代碼變動(dòng)所導(dǎo)致的影響芳肌,都在一個(gè)倉(cāng)庫(kù)里面,所以都屬于原子性的變動(dòng)肋层。因此亿笤,很容易撤銷(xiāo),或者預(yù)先測(cè)試它所造成的影響槽驶。
為了防止錯(cuò)誤提交责嚷,谷歌引入了”預(yù)提交”(即在提交之前,先分析一下依賴(lài)它的代碼是否會(huì)構(gòu)建失數囝怼)罕拂。
(5)大規(guī)模代碼析構(gòu)
單一代碼倉(cāng)庫(kù)為查找和分析代碼,提供了巨大的方便全陨。
Google的靜態(tài)分析引擎 Tricorder 定時(shí)運(yùn)行爆班,對(duì)代碼進(jìn)行分析。比如辱姨,C++ 11 標(biāo)準(zhǔn)公布以后柿菩,很容易找到所有需要改進(jìn)的變量聲明語(yǔ)句,進(jìn)行性能優(yōu)化雨涛。該引擎還對(duì)許多錯(cuò)誤提供"一鍵修正"的功能枢舶,同時(shí)產(chǎn)出大量的統(tǒng)計(jì)數(shù)據(jù)。
此外替久,編譯器團(tuán)隊(duì)也會(huì)對(duì)不同語(yǔ)言的所有代碼進(jìn)行分析凉泄,找出不合理的代碼和過(guò)時(shí)的API。
單一代碼倉(cāng)庫(kù)的缺點(diǎn)
單一代碼倉(cāng)庫(kù)的主要缺點(diǎn)是蚯根,所有工具都必須自己寫(xiě)后众,因?yàn)槭袌?chǎng)上沒(méi)有能夠管理這種規(guī)模的代碼倉(cāng)庫(kù)的軟件。
總結(jié)
單一代碼倉(cāng)庫(kù)颅拦,適合提倡透明開(kāi)放的大型軟件公司蒂誉,不適合小公司和有大量私密代碼的公司。
六一快樂(lè)啊小朋友們距帅!
學(xué)習(xí)從來(lái)不是一個(gè)人的事情右锨,要有個(gè)相互監(jiān)督的伙伴,工作需要學(xué)習(xí)python或者為了入行锥债、轉(zhuǎn)行學(xué)習(xí)python的伙伴可以私信回復(fù)小編“學(xué)習(xí)”陡蝇,資源共享和大牛面對(duì)面交流
原文:阮一峰的網(wǎng)絡(luò)日志