隨著時間的推移,軟件行業(yè)已經(jīng)提出了多種方法來更快更好更安全地交付代碼。其中大部分的努力都集中在諸如持續(xù)集成、持續(xù)交付、敏捷開發(fā)、DevOps 和測試驅動開發(fā)等方面。所有這些方法都有一個共同的目標:讓開發(fā)人員能夠以安全、小型和漸進的步驟將代碼快速正確地提供給用戶。
Facebook 的開發(fā)和部署過程已經(jīng)得到有機地發(fā)展,以涵蓋這些快速迭代技術的大部分內容,同時也避免特殊依賴任何一項單獨的技術。這種靈活、實用的方法使我們能夠在快速的時間內成功地發(fā)布我們的網(wǎng)絡和移動產(chǎn)品。
多年來,我們使用簡單的主程序發(fā)布分支策略每天部署三次代碼到 Facebook 前端。工程師們會從主干分支中選擇一些通過了一系列自動化測試的代碼變更推送到每天的發(fā)布分支上(這個過程也叫做“cherry-picking”)。總的來說,我們每天選擇的變更(cherry-picks)數(shù)量為 500 到 700。剩下的沒有被 cherry-picked 的變更就推入到每周的發(fā)布分支中。
從 2007 年的幾位工程師到現(xiàn)在的數(shù)千名工程師,這個系統(tǒng)的擴展性一直很好。好消息是,隨著我們增加了更多的工程師,我們完成的工作也越來越多——代碼交付的速度與團隊的規(guī)模成比例。然而,除了適當?shù)墓ぞ吆妥詣踊到y(tǒng)之外,它還需要發(fā)布工程師花費一定的手工勞動,來完成每天和每周的代碼推送和發(fā)布。我們知道,隨著團隊的不斷擴大,批量處理日漸增多的交付代碼塊將無法持續(xù)。
到了 2016 年,我們看到 branch/cherry-pick 模型已經(jīng)達到了極限。我們每天接收的推送到主分支上的變更超過 1000 個,而每周的接收的變更有時多達 10,000 個。因此每周需要進行大量的手工工作來協(xié)調和交付這樣大型的發(fā)布任務,這是不可持續(xù)的。
2016年4月,我們決定將 facebook.com 移到一個準持續(xù)的“push-from-master”系統(tǒng)上。在接下來的一年里,我們逐漸把它推出,首先讓50%的員工用上新代碼,然后讓0.1%的生產(chǎn)環(huán)境用上新代碼,再到1%,再增加到10%。這些進程中的每一步都是對我們的工具和過程的測試,測試它們處理日益增加的推送頻率的能力,從而得到真實的反饋。我們的主要目標是確保新系統(tǒng)能讓人們的體驗更好——或者至少,不會讓它變得更糟。經(jīng)過了幾乎整整一年的規(guī)劃和開發(fā)之后,在2017年4月的3天內,我們使100%的生產(chǎn)環(huán)境能夠運行直接從master部署的代碼。
大規(guī)模持續(xù)交付
雖然一個真正的持續(xù)交付系統(tǒng)會將每一次提交的代碼變更及時發(fā)布到生產(chǎn)環(huán)境中,但根據(jù)Facebook的代碼提交速度,我們需要開發(fā)一個每隔幾個小時就能處理數(shù)十到數(shù)百個代碼變更的系統(tǒng)。在這種準連續(xù)交付模式中所做的改變通常是小型且增量的,很少會對實際的用戶體驗有明顯的影響。每一次發(fā)布都以分層的方式在幾小時內部署到100%的生產(chǎn)環(huán)境,因此一旦發(fā)現(xiàn)任何問題,我們可以隨時停止發(fā)布。
首先,代碼變更通過一系列自動化的內部測試后才能被提交到主分支,進而被推送給Facebook的員工。在這一階段引入的任何回歸,都會使我們收到推送阻塞警報,而有個緊急停止按鈕也可以使我們阻止代碼的進一步發(fā)布。如果一切正常,我們會將變更推送到2%的生產(chǎn)環(huán)境,在那里我們會繼續(xù)收集信號和監(jiān)測警報,尤其是對于那些我們的自動測試和員工的內部測試沒有發(fā)現(xiàn)的邊界情況。最后,我們才將這些變更100%部署到生產(chǎn)環(huán)境中,由名為Flytrap的工具收集用戶報告,并在異常時給我們發(fā)送警報。
許多變更最初都是由 Gatekeeper 系統(tǒng)控制的,這使得我們能夠獨立地發(fā)布移動端和 web 端代碼而不依賴于新功能,同時有助于降低由任何特定更新導致問題的風險。如果確實發(fā)現(xiàn)了問題,我們只需要關閉 gatekeeper,而不是回退到之前的版本或修復當前版本。
這個準持續(xù)(”quasi-continuous”)發(fā)布周期有幾個優(yōu)點:
1. 它不再需要熱補丁
在每天部署三次的策略下,如果一個關鍵變更必須立刻發(fā)布,而不是在它預定的推送時間里,這時就必須有人來打熱補丁。這些帶外推送是破壞性的,因為他們通常需要一些人力操作,而且可能會撞上下一個預定的推送。在新系統(tǒng)中,絕大多數(shù)需要熱補丁的程序都可以簡單地提交給master,并在下一個版本中進行發(fā)布。
2. 為全球工程師團隊提供了更好支持
我們試著盡量合理安排每天三次部署的時間,以適應我們在世界各地的工程辦公室。但即使是這樣的努力,每周一次的發(fā)布也要求所有的工程師在某個特定的日期和時間內集中注意力,然而這些時間在他們的時區(qū)并不總是很方便。新的準持續(xù)系統(tǒng)意味著世界各地的工程師都可以根據(jù)需要開發(fā)并交付的代碼。
3. 它迫使我們開發(fā)下一代工具、自動化和流程,以使公司能夠擴大規(guī)模
我們所做的這個項目,可以作為跨越多個團隊和系統(tǒng)的壓力測試。我們改進了推動工具、diff 審查工具、測試基礎架構、容量管理系統(tǒng)、流量路由系統(tǒng),以及許多其他方面。這些團隊都聚集在了一起,因為他們希望看到一個發(fā)布周期更快的自動化部署系統(tǒng)盡快成功。我們所做的改進將有助于確保公司為未來的發(fā)展做好準備。
4. 它使用戶體驗更好、更快
當需要數(shù)天或數(shù)周的時間來觀察代碼的運行狀況時,工程師們可能已經(jīng)轉向了新的任務。在持續(xù)交付的情況下,工程師不必等待一周或更長的時間才能得到他們提交的代碼的反饋。他們可以更快地了解到哪些地方不work,并及時進行小的增強或修復,而不是等到下一次大的發(fā)布。從基礎設施的角度來看,新系統(tǒng)使我們能夠更好地應對那些可能影響用戶的稀有事件。最終,這將使工程師更加貼近用戶,不僅有助于產(chǎn)品開發(fā)還有助于提高產(chǎn)品可靠性。
持續(xù)發(fā)布到移動端
在web平臺上發(fā)展出一個準連續(xù)系統(tǒng)在某種程度上是可能的,因為我們擁有完整的技術棧,而且可以構建和改進我們需要的工具,使之成為現(xiàn)實。而移動平臺上則面臨更多的挑戰(zhàn),因為許多現(xiàn)有的移動平臺的開發(fā)和部署工具使快速的迭代變得比較困難。
Facebook致力于改善這一情況,并建立和開源了一整套專門針對移動平臺上快速開發(fā)的工具,包括Nuclide、Buck、Phabricator、各種iOS類庫、React Native和Infer。總之,這一系列構建和測試棧使我們能夠產(chǎn)生高質量的代碼,以便快速部署到移動平臺上。
我們的持續(xù)集成棧主要分成三層:構建、靜態(tài)分析和測試。
當開發(fā)人員將代碼提交到移動主分支時,會在所有受影響的產(chǎn)品上對代碼進行構建。對于移動端來說,這意味著每次提交都要重新構建Facebook、Messenger、Pages Manager、Instagram以及其他應用程序。我們還為每個產(chǎn)品構建了多個版本,以確保能夠涵蓋這些產(chǎn)品支持的所有芯片架構和模擬器。
在構建過程中,我們會運行Infer,它集合了Linters(檢查代碼風格和錯誤的小工具)和靜態(tài)分析工具,用于捕獲空指針異常、資源和內存泄漏、未使用的變量和有風險的系統(tǒng)調用,并標記出違反Facebook編碼規(guī)則的情況。
第三個并發(fā)系統(tǒng)是移動自動化測試,包括數(shù)千個單元測試、集成測試以及由Robolectric、XCTest、JUnit和WebDriver等工具驅動的端到端的測試。
不僅每次提交時會運行構建和測試棧,而且在代碼變更的生命周期內也會運行多次。僅在安卓系統(tǒng)上,我們每天就能完成5萬到6萬次構建。
通過將傳統(tǒng)的持續(xù)交付技術應用到移動棧,我們已經(jīng)從四周發(fā)布一版發(fā)展到兩周發(fā)布一版,再到現(xiàn)在的一周發(fā)布一版。目前我們在移動平臺上使用的就是之前基于web的策略:branch/ cherry- pick模型。雖然我們每周只發(fā)布一個版本,但在現(xiàn)實環(huán)境中盡早測試代碼仍然很重要,因為這樣工程師就可以盡快得到反饋。我們每天都會為我們的金絲雀用戶(包括大約100萬個Android beta測試人員)提供新的移動候選版本。
與此同時,我們的發(fā)布頻率增加了,我們的移動工程師團隊已經(jīng)增長了15倍,我們的代碼交付速度也已經(jīng)大大提高。盡管如此,從我們2012年到2016年的數(shù)據(jù)來看,無論是按代碼行數(shù)還是按推送數(shù)量來衡量,工程師在Android和IOS方面的生產(chǎn)率都保持不變。同樣,無論部署多少次,移動版本出現(xiàn)的關鍵問題的數(shù)量幾乎沒有變化,這說明我們的代碼質量并沒有隨著代碼規(guī)模的增大而受到影響。
隨著現(xiàn)有的工具和方法不斷取得進展,這是在發(fā)布工程領域工作的一個令人興奮的時刻。我為Facebook的團隊感到非常自豪,他們一起合作為我們提供了我認為是這個規(guī)模下最先進的web和移動部署系統(tǒng)。這一切能成為可能還有一部分原因是擁有一個強大的中央發(fā)布工程團隊,因為它是基礎設施工程領域的“第一類公民”(First-class citizen)。Facebook的發(fā)布團隊將繼續(xù)為開發(fā)人員和用戶推動改善發(fā)布流程的計劃,也會繼續(xù)分享我們的經(jīng)驗、工具和最佳實踐。
如有問題請聯(lián)系我們,我們7*24小時竭誠為您服務