色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

持續(xù)集成之“依賴管理”

  在前文《分支策略(續(xù))》中,我們討論了多組件應(yīng)用程序的持續(xù)集成策略,即:為相對獨立的組件創(chuàng)建自己專屬的代碼庫,然后通過現(xiàn)代持續(xù)集成工具進行組件間的持續(xù)集成。Joe的團隊在首次發(fā)布之后,開始使用這種方式。然而,沒有多久,他們就遇到了一個問題:一次提交構(gòu)建所花費的時間太長。

  一天,Joe就早早地來到了辦公室。因為他前一天下班前,他開發(fā)的用戶故事還有一小點就完事兒了。他想利用早上這點兒時間把它搞完,交給測試人員進行測試。他修改了某個模塊的一段代碼,在本地構(gòu)建測試通過以后,就提交了, 然后起身去樓下買些早點。十五分鐘后,他回到了電腦前,令他沮喪的是,這次構(gòu)建還在進行最后的階段,即所有模塊集成測試和系統(tǒng)級測試。他只好又起身去沖了杯咖啡。然后,一邊看著屏幕上的構(gòu)建進度條,一邊喝著咖啡。七分鐘后,構(gòu)建終于成功結(jié)束了。雖然這是一次成功的構(gòu)建,但總是覺得不爽,花了二十多分鐘才做完提交構(gòu)建。于是,他開始仔細地查看起構(gòu)建腳本和構(gòu)建日志。

  一、一次生成,多次復(fù)用

  中午吃過午飯,他把Bob和Alice叫到一起,開始討論早上他遇到的問題。

  “的確是非常煩人,現(xiàn)在構(gòu)建時間太長了。”Alice說道。

  “我今天早上查看了一下我們的構(gòu)建日志,發(fā)現(xiàn)構(gòu)建時間長的原因之一是:每種測試開始之前都要更新代碼,再重新編譯一次。”Joe說道。

  Bob提出了一個解決方案,并畫在了白板上。“我們是否可以建立統(tǒng)一的產(chǎn)物庫,每次構(gòu)建的產(chǎn)物都以一定的規(guī)則放在其中?這樣,后續(xù)的測試需要使用這些二進制產(chǎn)物的話,直接從產(chǎn)物庫中獲取即可。”(如圖1所示)

  “聽上去不錯。然而,我們是否需要把每次構(gòu)建中產(chǎn)生的內(nèi)容都放入產(chǎn)物庫,這會非常快地吃掉我們的磁盤空間。”Alice不無擔(dān)心的說。

  “目前構(gòu)建完成以后,所有的產(chǎn)物都放在那臺構(gòu)建機器上。我們也遇到過因構(gòu)建機器硬件問題或誤操作將所有重要歷史信息都丟失的事情。所以,我們至少需要備份。”Bob回答道,“另外,將每次構(gòu)建的產(chǎn)物放在統(tǒng)一產(chǎn)物庫中,我們就可以解決Joe剛才提出的重復(fù)編譯問題。當(dāng)然,我們需要有選擇地將重要的構(gòu)建產(chǎn)物放到統(tǒng)一產(chǎn)物庫中,而不是所有內(nèi)容。通過在每次構(gòu)建后增加一個上傳任務(wù),讓各小組將其認為有用的信息上傳到產(chǎn)物庫,比如構(gòu)建日志、測試報告、構(gòu)建后的二進制文件等。但一些臨時文件就沒有必要了。當(dāng)然,這只能緩解產(chǎn)物庫膨脹的速度。盡管持續(xù)構(gòu)建的次數(shù)非常多,但我們并不是需要一直保持所有構(gòu)建的產(chǎn)物,所以,可以定期刪除那些沒有保留價值的構(gòu)建產(chǎn)物,比如對那些重要構(gòu)建的產(chǎn)物進行標(biāo)記,其它的就可以刪除了。”

  Alice和Joe都點了點頭,表示同意。但Joe的眉頭馬上又皺了起來。“嗯,好象這里還有點兒問題。”

  “什么問題?”Alice和Bob同時問道。

  Joe說道:“對于我們平臺中的一些小游戲組件來說,這沒有什么問題。因為它們的構(gòu)建產(chǎn)物都不太大,網(wǎng)絡(luò)傳輸帶寬和速度都不是問題。但是,對于那些很大的二進制文件或測試數(shù)據(jù)來說,這么做的話,可能就有問題了。”大家都點了點頭,并開始思考這個問題。

  忽然,Joe叫道:“不好意思,其實這不是個真正的問題。首先,我們的測試數(shù)據(jù)變化就不頻繁,原來也沒有放在產(chǎn)物庫中,而是放在了一個共享目錄中進行版本管理。所以,這部分在構(gòu)建中的做法與之前沒有什么不同。其次,對于較大的二進制文件,只要在需要它的構(gòu)建機器上把它緩存起來。那么在下一次構(gòu)建時,構(gòu)建腳本可以對這個本地版本進行驗證,如果版本正確且沒有被破壞(比如通過MD5驗證)就可以繼續(xù)使用。否則,就再從統(tǒng)一產(chǎn)品庫取出正確的文件將其覆蓋就行了。”

  “這么做還有一個好處,而且是非常重要的好處。”Alice補充道,“我們的手工測試版本也可以從統(tǒng)一的產(chǎn)物庫中拿到,這就保證了自動化測試所有的二進制文件與部署到手工測試環(huán)境中的二進制文件是同一個文件了,也就不會出現(xiàn)因重新編譯時的環(huán)境不同而導(dǎo)致的不一致問題了。而當(dāng)我們做上線部署時,也從這個統(tǒng)一產(chǎn)品庫中獲取,從而做到自編譯開始直到上線部署的二進制包的一致性啦。”

  于是,Joe與團隊一起對其持續(xù)集成平臺和所有構(gòu)建進行了改造,將其打造成了一個具有組織級產(chǎn)物庫的持續(xù)集成和發(fā)布管理平臺。他們不但有效地縮短了每次構(gòu)建的時間,還可以輕松地通過產(chǎn)物庫追蹤到每個上線版本在代碼版本控制庫中的對應(yīng)代碼,讓問題追查變得更容易了。

  二、依賴管理

  一個月后,根據(jù)市場的需求反饋,他們開發(fā)的一個游戲升級了,反應(yīng)速度非常快,效果非常好。但引申出來的一個問題是:游戲和平臺的升級頻率不一致,持續(xù)集成應(yīng)該怎么做。對于Joe的團隊來說,是一個非常大的問題,因為他們的開發(fā)流程嚴重地依賴于持續(xù)集成平臺。于是,Joe和團隊的核心成員打算討論一下,如何應(yīng)對目前這種情況。

  在會議室的白板前,Joe畫出了當(dāng)前所用的持續(xù)集成策略(如前圖所示)。

  Bob說道:“到目前為止,我們已經(jīng)發(fā)布了幾次,而且最近一次只發(fā)布了一個游戲應(yīng)用。我們?nèi)绾喂芾砦覀兊陌l(fā)布流程呢?在我之前工作過的公司中,產(chǎn)品會有幾個版本,包括穩(wěn)定版本、已對外發(fā)布或即將發(fā)布的版本、最新版本:用于公司內(nèi)部測試。每當(dāng)將要發(fā)布新版本時,就拉出一個分支,進行內(nèi)部測試,并修復(fù)嚴重的缺陷。當(dāng)沒有嚴重缺陷時,才能作為穩(wěn)定版本公開發(fā)布。”

  Alice答道:“對于單個的軟件交付產(chǎn)品來說,通常可以通過“按發(fā)布拉分支” 的方式進行開發(fā),正如我們最開始所使用的持續(xù)集成策略。但是,現(xiàn)在我們的游戲平臺與單個交付產(chǎn)品不同。我們有自己的服務(wù)器集群,只要測試覆蓋率及測試質(zhì)量足夠好,測試速度足夠快,我們就可以通過小流量試驗部署后再大規(guī)模上線的方式進行發(fā)布。現(xiàn)在,我們的問題是由于各個游戲組件的發(fā)布頻率各不相同,組件存在依賴關(guān)系,導(dǎo)致很難決定在持續(xù)集成過程中,到底應(yīng)該使用哪個依賴版本。尤其是我們現(xiàn)在還有一個公共庫,被多個組件使用。”

  Joe說道:“我們先梳理一下整個平臺上的依賴關(guān)系吧。通常來說,軟件中的依賴關(guān)系通常包括編譯時依賴、測試時依賴和運行時依賴。而從依賴形式上可以分為庫依賴和組件依賴。所謂庫依賴,是指依賴于那些不受控的庫文件,比如我們使用了一些開源或者付費的的類庫文件或工具,這些庫文件的特點是更新較慢,甚至基本不需要更新。而組件依賴是指依賴于那些由自己團隊或公司內(nèi)的其它團隊開發(fā)的組件,這類依賴的特點是更新頻率相對高,有些甚至非常頻繁。對于庫文件依賴,我們可以在代碼庫中建立一個目錄,叫做lib,并在其下建立build、test、run三個子目錄,把我們所依賴的庫文件放到相應(yīng)的子目錄中。同時,每個庫文件的文件名中最好包含它的版本號,如nunit-2.6.0.11089.bin。這樣,就很容易看出依賴了哪些庫文件。”

    Bob接道:“可惜我們不是用Java平臺,否則我們可以用象MavenIvy這樣的工具來管理這些外部庫依賴了。而且,同時可以在公司內(nèi)部利用Artifactory或Nexus這樣的開源工具建立一個內(nèi)部統(tǒng)一服務(wù)器,專門管理公司內(nèi)部所用的這些庫依賴。”

    Alice說道:“我們也可以自己做一個簡單的依賴管理系統(tǒng)。比如使用Key-value的格式用文本文件來描述所用到的庫文件名及版本號及存放位置,然后再寫個通用腳本讀取信息下載到本地使用。”

    Bob接著問道:“對于這種庫文件的依賴管理相對容易一些。而我們面臨的重要問題好象是組件依賴管理。有什么好辦法嗎?”

    Joe想了想,說道:“方法倒是有幾個,各有優(yōu)缺點。一種方法是將組件依賴轉(zhuǎn)成庫依賴。其適用的場景是該組件經(jīng)過一段時間的開發(fā)的維護后已趨于穩(wěn)定,變化不太多。此時就可以將這個組件打包后與其它外部依賴庫放在一起,并加入正確的描述,以便依賴于它的所有組件都可以正確地拿到正確的版本。還有一種方法是我們目前所用的方法。即每個組件各自進行持續(xù)構(gòu)建,然后再做集成構(gòu)建。其中存在的問題是我們?nèi)绾喂芾砀鹘M件不同版本之間的組合關(guān)系。我們一直使用的策略是無論哪次提交,都會觸發(fā)整個構(gòu)建。目前要做的有兩件事:一是將公共庫獨立出來,進行單獨構(gòu)建,并且一旦構(gòu)建成功,自動觸發(fā)那些依賴于它的其它組件構(gòu)建,最后進行集成構(gòu)建。只要我們記錄每次構(gòu)建后的版本及源代碼的revision就行,以便可以追蹤。二是將游戲平臺的持續(xù)構(gòu)建觸發(fā)其它游戲組件的持續(xù)集成。所以,觸發(fā)關(guān)系應(yīng)該是這樣的。”Joe拿起筆,在白板上重新畫了一下觸發(fā)關(guān)系圖(圖2)。

    Bob搖了搖頭,說道:“這樣還是解決不了我們之前說過的問題,即我們的發(fā)布頻率不一致,如何來管理這些發(fā)布之間的關(guān)系。”

    “噢,這個問題是這樣的。”Joe回答道:“我認為,我們之前單獨發(fā)布一個游戲組件是不對的。我們因市場壓力而將該游戲組件直接部署到生產(chǎn)環(huán)境中,盡管在發(fā)布前的評估認為,該游戲所依賴的平臺接口沒有發(fā)生變化。正確的做法有兩種:(方案A)將平臺作為一個整體一同發(fā)布,因為我們對平臺也做了修改,當(dāng)時,所有的持續(xù)集成測試都是基于主干的最新版本所做的。(方案B)讓所有游戲組件依賴于游戲平臺的最新發(fā)布的穩(wěn)定版本進行開發(fā)。由于平臺的新功能開發(fā)較慢,所以只要平臺接口不發(fā)生變更,各游戲應(yīng)用都可以基于平臺的穩(wěn)定發(fā)布版本進行快速更新。但只要某個游戲需要修改平臺的接口,就必須與平臺的最新代碼進行持續(xù)集成,并一同發(fā)布。”

    Alice皺了皺眉,說道:“這么看來,對于整個軟件來說,能夠保持主干隨時可以發(fā)布才更容易管理組件依賴。因為每當(dāng)需要發(fā)布時,直接做主干發(fā)布就行了。實在不行的話,只要將所有組件在同一時間點拉出一個發(fā)布分支,然后統(tǒng)一上線就行了。”

    Bob說道:“這樣也有問題。我們的部署會很麻煩,時間可能會很長。”

    Joe笑著說:“部署麻煩,我們可以通過一系統(tǒng)列的自動化操作來解決。部署時間長的話,我們使用的是集群部署,因此可以采用分批替換的方式來部署。但這種發(fā)布方式給我們帶來的益處是可以很快的響應(yīng)市場需求。”

    Joe拿起杯子喝了口咖啡,接著說道:“當(dāng)然,這對我們的開發(fā)工作也提出了挑戰(zhàn)。我們必須使用多種手段才能做到主干持續(xù)可發(fā)布狀態(tài)。比如(1)將新功能隱蔽起來,直到它完成為止;(2)把所有的變更都變成一次次非常小的增量式修改,每個修改都做到可發(fā)布;(3)通過抽象達到分支的目的(Branch by Abstraction)。另外,我們的自動化測試也需要保持在較高的覆蓋率,并豐富其它類型的自動化測試,比如性能測試,壓力測試等。如果遇到特殊情況,我們再坐下來商量對策。”

    Bob仍舊有點遲疑,“這樣可能會增加我們的開發(fā)成本。不過,可以試一下,看看效果如何。”

    于是,整個團隊開始行動起來了。他們在這條道路上還會遇到什么情況呢?讓時間來回答這個問題吧。

it知識庫持續(xù)集成之“依賴管理”,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 肥东县| 崇左市| 阿坝| 芦溪县| 昌黎县| 巢湖市| 皋兰县| 东乌珠穆沁旗| 台安县| 宣汉县| 东乌| 达孜县| 扎赉特旗| 毕节市| 六枝特区| 赤峰市| 贵溪市| 沅江市| 南和县| 尚志市| 福清市| 闵行区| 尤溪县| 石楼县| 马山县| 兴国县| 正宁县| 曲靖市| 万全县| 珠海市| 洱源县| 新河县| 郸城县| 虹口区| 丰城市| 福泉市| 岳阳市| 周宁县| 江孜县| 元阳县| 陆丰市|