本文原文在google開發者工具組的博客上[需要翻牆],以下是我的翻譯,歡迎轉載,但尊重作者版權,注名原文地址。
在Google,所有的產品都是在主干上開發的。這樣的好處:每個人都可以查看和修改代碼,避免了在分支上長時間開發后合並主干時候的痛苦,從源碼構建也避免了庫之間的二進制兼容問題。Google是跨國公司,這意味着分布在世界各地的辦公室會放大下載代碼的時間。通過計算依賴關系來限制下載的文件數量,我們成功地減少了代碼下載的時間。然而,計算依賴關系也要花時間,而且即使這樣改進了,獲取源碼的時間仍然很長。
最明顯的代價是工程師花費在下載代碼上的時間,而實際上的代價更高。自動化構建和測試需要訪問源碼。在這些系統中下載代碼上花費的時間會增加整個過程的時間,同時也會增加這些系統的復雜度,因為他們需要在文件系統上維護狀態並為了獲得代碼的只讀權限而和版本控制系統緊密耦合。
實際上,我們發現工程師下載代碼后修改的代碼相對於執行構建需要的代碼而言是非常小的一部分。因為我們所有的東西都是從代碼構建的,而修改的只是源碼樹中的一小部分。所以,工程師和自動構建系統都需要對執行構建所需要的未修改的大量代碼擁有一個更快,只讀的訪問方式。未修改的代碼本身是沒有發生變化的,因為自動提交到版本管理系統后,就沒有改動過。這意味着我們可以使用Google的基礎設施來在雲上對所有的版本控制信息做鏡像來對源碼提供更快且可擴展的只讀訪問。
在我們系統中,每個文件的每個版本都有對應的元信息記錄。元信息包含的信息包括:文件在代碼庫里面的路徑信息,文件名稱,大小,版本號等,也包含了針對這個版本的文件內容的摘要。這個摘要是使用適合基於內容尋址存儲CAS的哈希函數來對文件內容的哈希。在系統中很多地方我們實現了CAS。在后續的文章會中讀到更多的CAS內容。
/som/path/foo.c文件的第5個版本的元信息和CAS的文件內容看起來是這樣的:
我們的系統監控版本控制系統中到來的修改。當發生修改后,我們哈希文件內容來計算摘要並把內容插入到BigTable存儲系統中。然后我們計算每個受影響的文件的元數據信息並插入到BigTable中。這樣我們就在雲上擁有了所有文件的各個版本的完整歷史。
現在我們有了這些數據,我們怎么使用它?我們在開發人員的本地機器上使用命令行工具來下載雲端的代碼。這樣能夠減少版本控制系統的負載,並由於使用的是在辦公地點附近的雲端數據拷貝,也會由於減少了網絡時延而提升性能。我們實現的時候不是下載全部代碼,而是自動按需下載代碼,這非常有用。
上面提到的按需自動下載代碼,可以通過實現一個定制的文件系統來完成,這個定制的文件系統提供對版本歷史的只讀訪問。通過用戶空間文件系統(File System in Userspace)可以很方便的用一個用戶態空間里的守護進程來實現這樣的文件系統。用戶使用跟其他文件系統一樣的方法來和這個源碼文件系統交互,唯一差別是路徑中有配置了版本信息的特殊元素。
例如,訪問前面例子里提到的foo.cc文件的1000版本:
文件系統通過類似stat()和readdir()這樣的調用來獲得元信息,首先是從路徑中解析出版本號,然后從雲上獲得版本控制數據。
例如,使用gcc(或者其他工具)來編譯foo.cc,gcc首先調用stat()來檢查文件是否存在:
這就允許用戶和工具僅僅使用版本元數據來訪問版本控制。文件內容只有在文件被打開的時候才會下載下來。由於文件版本是不可變的,所以文件內容可以緩存下來並無限次的重復使用[文件內容和元數據在本地有緩存]。CAS的使用同時也消除了文件內容的重復數據,相同的內容不會重復下載。
通過把版本歷史存儲在雲端,我們就可以讓開發人員訪問到所有的代碼的同時,還能夠保證下載時間非常短。通過把雲擴展到多個地理區域,就可以保證世界各地的辦公區的性能都差不多。最終,自動化的構建和測試系統可以通過簡單的文件系統接口來而很容易的獲得代碼而不用跟版本控制工具直接打交道。所有這些組成了一個快速高效的系統來保證工程師和自動化的系統可以專注於構建和測試軟件而不是下載源碼上。
如果您看了本篇博客,覺得對您有所收獲,請點擊右下角的“推薦”,讓更多人看到!

