阿里雲效團隊大規模程式碼構建技術實踐

dicyt發表於2017-07-31

摘要: 在雲棲社群舉辦的線上直播中,來自阿里巴巴雲效團隊的何衛龍為大家帶來了《大規模程式碼構建技術實踐》的分享。本次分享主要從持續整合的背景,持續整合平臺的演進過程以及如何大規模持續整合構建三部分展開,內容精彩,不容錯過。

原文地址:

http://click.aliyun.com/m/27112/


什麼是持續整合?

大師Martin Fowler認為持續整合是一種軟體開發實踐,在實踐中團隊開發成員會頻繁的進行任務的整合,通常每個成員每天都會整合一次,也就意味著每天可能會發生多次整合。每次整合都通過自動化的構建來驗證,從而儘快地發現整合錯誤,快速進行修復。

 

如上圖所示,一個完整的持續整合環節包括:首先專案經理建立一個專案,將專案成員新增到專案中;開發人員在專案中拉取開發分支進行程式碼開發,在開發過程中,開發人員將程式碼提交到程式碼倉庫(如SN、GIT);後端的持續整合任務會定時掃描程式碼倉庫,如果發現程式碼有變更,馬上觸發一次CI構建,一次CI包括原始碼下載、程式碼編譯、靜態掃描、單元測試、覆蓋率分析、sona檢查、環境打包部署、自動化用例執行等;再以訊息的形式反饋結果給程式碼提交人或者專案關注人。訊息的形式有兩種,一種是即時訊息,如阿里內部的旺旺、釘釘,讓開發人員第一時間收到CI結果概況,如有問題,可以進行快速修復;另一種是郵件通知,可以看到CI結果詳情,幫助問題的定位和跟蹤,有益於驅動大家修復問題。

持續整合的優勢

持續整合有哪些好處呢?

 

首先來看一幅圖,大家應該都比較熟悉,冰山一角,如果把它移植到研發測試流程上面來講,我們看的到的冰山,就好比開發階段發現的Bug,比起海面以下的冰山,簡直就是小巫見大巫。因此,持續整合給我們帶來的直接好處,就是不斷的發現海面以下的Bug,讓我們能在開發階段儘可能多的解決問題;其次,Bug越往後面發現,處理它的成本會越高,付出的代價也越大,因此,持續整合能幫助到我們降低專案研發成本;最後,如右側圖片所示,當持續整合不斷的完善專案時,會潛移默化的推動著我們測試前移的動作,從沒有整合的1,到整合初期的2,最終不斷完善的整合3,成本越來越低、程式碼質量越來越高、釋出時間越來越短 、從而使產品的品質越來越好。

持續整合涉及整個專案生命週期的人員,包括需求方、開發、測試、產品經理等。對於開發人員,他們希望能有單測、覆蓋率、findbugs、sonar等自動化整合工具,儘早發現缺陷,這樣流入測試環節的問題就會變少,從而保證程式碼質量;對於測試人員,他們希望儘早整合發現缺陷,提高待測質量,降低專案風險;產品經理則希望專案能按期、保質保量的安全上線。因此我們需要一個持續整合平臺來保障上述利益。

平臺演進

下面來介紹一下平臺演進的過程。

 

主流的持續整合工具主要有:

  • Jenkins,它的前身是Hudson ,是一個可擴充套件的持續整合引擎。它的功能比較強大,支援分散式任務構建。

  • GoCD,一款先進的持續整合和釋出管理系統,由ThoughtWorks開發,其前身為CruiseControl,是ThoughtWorks在做諮詢和交付交付專案時自己開發的一款開源的持續整合工具,ThoughtWorks專門成立了一個專案組,基於Cruise開發出了GoCD這款工具。使用GoCD來建立起一個專案的持續部署pipeline是非常快的,非常方便,它的不足點是外掛較少、開源時間短、使用者群體較小;

  • Apache continuum,其安裝和配置都較為方便;

  • Strider 是一個開源的持續整合和釋出伺服器,使用 Node.js 開發;

  • TeamCity是一款功能強大的持續整合(Continue Integration)工具,包括伺服器端和客戶端,目前支援Java、.Net專案開發,是一款商業軟體;

  • Atlassian Bamboo 是一款持續整合構建伺服器軟體(Build Server)商業軟體;

  • Travis CI是一個基於雲的持續整合專案,目前已經支援大部分主流語言了,比如C、PHP、Ruby、Python、Nodejs等。和Jenkins類似,Travis CI也是開源的,不過Travis和Github整合非常緊密,官方的整合測試託管只支援Github專案, 不過使用者也可以搭建一套自己的方案。 

通過對上述持續整合工具的比較,阿里最終選擇了Jenkins這一工具,Jenkins作為一款開源軟體,有著豐富的外掛(目前已達幾百個),還可以自定義外掛以及修改或增加Jenkins擴充套件點,來進行Jenkins功能擴充套件。

 

對於小團隊而言,Jenkins完全可以滿足需求了,但是對於一個成百上千,甚至更多人的團隊來講,就顯得有點弱了。第一,Jenkins不能自動建立Jenkins任務,必須在Jenkins平臺上手工建立,大大降低了整合效率,而且需要大家都掌握建立Job的方法以及Job上的配置,不利於工具推廣;第二,其資料顯示不能定製化,如果想要整合資料在一個頁面上顯示,那麼Jenkins是無法滿足這個要求的;第三,資料不能持久化,目前Jenkins的資料是通過文字的方式儲存的,而且量很大,不利於資料維護和後續的資料分析;第四,執行機掉線沒有報警功能,不會及時通知管理員及時處理;第五,資料反饋機制比較單一,Jenkins僅支援郵件的方式進行傳送通知;第六,通過專案資訊查詢任務困難,Jenkins沒有專案的維度,只有Job的維度,不方便查詢。

因此,單測整合平臺Amon應運而生,它始於2012年,目前已有10多家公司,正在使用這一產品。Amon的優勢在於其任務全自動構建,並支援大規模整合、資料持久化,具有豐富的報表和多維度的資料分析,Amon和Jenkins詳細功能對比如上圖所示,這裡不再一一敘述。

 

我們針對Jenkins外掛進行了新增和修改,以便它們適應於Amon,主要包括:

  • Maven pom內容修改外掛,它能滿足一些特定功能;

  • Maven多模組構建外掛,支援多路徑發現pom檔案;

  • MQ構建結果通知外掛,它能夠通過訊息的形式傳送到平臺;

  • Hosts修改外掛,以此支援特定服務的測試;

  • Cppcheck編譯掃描結果外掛;

  • Antx檔案自動生成外掛;

  • 支援cobertura結果合併外掛;

  • 支援cobertura增量覆蓋率外掛;

  • 支援jshint掃描外掛

  • 支援多執行機空間清理外掛

  • Sonar-runner自動找java路徑

整合實踐

目前,阿里內部整合狀況是支援10w+的日均構建數,平均每秒發生四次構建,這是一個非常龐大的量。我們的平臺是如何來做支撐的呢?

 

首先,系統通過負載均衡模組將整合任務分配至各叢集中;在每個叢集中都有大量Jenkins機器來做持續整合構建,它是可以進行橫向擴充套件的,因此我們就能很好地進行大規模的構建。在構建過程中,難免會有一些任務排隊等待,這樣會導致一些使用者等待時間較久。

我們針對這一情況進行了優化:相同叢集的Slave可以靈活、自由排程,如果某臺Jenkins任務比較吃緊,它就會從最空閒的Jenkins上排程一臺Slave過來支援當前的任務構建,以解決任務排隊嚴重的問題。但是,過於頻繁的Slave排程勢必會影響到系統處理時間和效能。因此,接下來將詳細講解負載均衡做到最優任務分配的原理。

 

這裡提到的負載均衡和常見的負載均衡還是存在差異的。這裡提到的負載均衡任務整合自驅的,也就是其可以定時自動構建,因此,你不太清楚一個任務一天回構建多少次,也不清楚一次構建的時長是多少。在分配任務的時候,可能比較難以選擇,如果仍然按照平均分配的方式,勢必會形成每個Jenkins上任務個數相同,但是基於每個任務的構建時長和頻率都存在差異,這樣又會導致一些Jenkins排隊非常嚴重,那麼如何解決這個問題呢?

首先需要了解一下Jenkins中的引數:其中n表示任務數、m表示執行機數、T表示最大構建負載(T=m*8*60),如超過最大負載值,任務排隊現象會加重;Jenkins第k個任務構建總耗時用tk(tk=任務最近一次構建耗時(分鐘)*該任務歷史日均構建次數)表示。根據上述引數,可以計算出Jenkins當前的負載值H,公式為:

利用當前的負載值,進行任務分配,做到最優化:當任務分配到Jenkins時,同時需要增加Jenkins的負載值以及修改該任務的平均耗時和平均構建頻率,不斷地調整,以便於趨於穩定;當任務關閉時,需要減去相應的時間來調整負載值。該演算法的思路較為簡單,但實現時比較困難,主要是由於任務的耗時和頻率會發生變化,需要實時調整以改變負載值,讓整合任務分配到最合適的Jenkins上去。

相關文章