Yelp是如何做到每天運行成千上萬個測試

Lerachee4a7u 7年前發布 | 68K 次閱讀 Mesos 程序員 軟件測試

快速進行功能開發對企業至關重要,開發團隊都試圖通過減少測試、配置和監控變化的時間來提高開發人員的效率。為了讓開發人員安全地敲代碼,Yelp使用內部分布式系統Seagull運行2000多萬個測試。

什么是Seagull?

Seagull是一個容錯和故障恢復的分布式系統,用來并行執行測試包。Seagull由以下幾部分組成:

  • Apache Mesos(管理Seagull集群上的資源)
  • AWS EC2(提供組成Seagull和Jenkins集群的實例)
  • AWS DynamoDB(存儲調度器的元數據)
  • Docker(隔離測試需要的服務)
  • Elasticsearch(追蹤測試運行次數和集群使用數據)
  • Jenkins(搭建代碼項目并運行Seagull調度器)
  • Kibana和SignalFx(提供監控和報警)
  • AWS S3(為測試日志提供真實數據來源

挑戰

在準備單片Web應用和Yelp主機配置新的生產代碼之前,Yelp開發人員在特定的主機上運行整個測試包。測試前,開發人員需啟動用來調度集群測試的Seagull。以下兩點需要著重考慮:

  • 性能:每個Seagull-run包含將近10萬個測試,依次運行完畢需要大約2天時間。
  • 規模:通常一天有300多個seagull-runs在運行,高峰時段要同時運行30-40個測試。

這項任務的挑戰在于執行每一個Seagull-run所花費的時間是以“分鐘”而不是以“天”來計算,同時保證在這個時間段內成本效益好。

Seagull怎樣運作?

首先,開發人員在控制臺啟動Seagull-run,即啟動Jenkins搭建代碼項目并生成測試列表。然后,將測試打包傳給Seagull集群上的調度器進行測試。最后,將測試結果存儲在Elasticsearch和S3中。

1、開發人員為特定的代碼版本(基于其分支git SHAs)啟動Seagull-run,設git分支為test_branch。

2、生成test_branch的代碼項目和測試列表并上傳到S3。

3、Bin Packer抓取測試列表和測試的歷史時序元數據,從而構建包含測試的多包。有效打包是一個裝箱問題,可以用以下兩個算法解決,(選擇哪種算法)取決于研發人員傳給Seagull的參數:

(1)、貪婪算法:首先根據歷史測試時長將測試分類,然后將測試時長設置為10分鐘的測試歸檔。

(2)、線性規劃(LP):為了防止相關測試,一個測試需要和另一個測試在同一個包里運行。因此,我們使用LP進行打包,LP方程的目標函數和約束條件定義如下:

1)目標函數:對生成的包總數取最小值

2)主要約束條件:

單包的測試時長少于10分鐘;

一個測試只能放入一個包;

相關測試放入同一個包。

我們使用Pulp LP解算器求解方程:

# Objective function:
problem = LpProblem('Minimize bundles', LpMinimize)
problem += lpSum([bundle[i] for i in range(max_bundles)]), 'Objective: Minimize bundles'

# One of the constraint, constraint (1), looks like:
for i in range(max_bundles):
    sum_of_test_durations = 0
    for test in all_tests:
        sum_of_test_durations += test_bundle[test, i] * test_durations[test]
    problem += (sum_of_test_durations) <= bundle_max_duration * bundle[i], ''

其中,bundle和test_bundle是LP變量,max_bundles和bundle_max_duration是整數。

通常,在LP約束條件中,我們會考慮測試用例的搭建和解除的時長,但是為了簡便,在這里我們忽略不計。

4、在Jenkins主機上啟動調度器進程,Jenkins主機抓包然后搭建mesos架構。我們為每一個Seagull-run創立一個新的調度器。每一次運行生成300多個包,將運行時長在10分鐘左右的包歸為一類。調度器為每一個包建立一個Mesos執行器,只要Mesos控制器提供充足的資源,就將Mesos執行器列入Seagull集群時間計劃表。

5、一旦執行器被列入到集群,執行器內部將進行以下步驟:

每一個執行器建立一個沙箱,從S3(在步驟(2)中已上傳)下載新建項目。然后下載對應于相關測試服務的Docker圖片就可以建立Docker容器(服務)了。當所有的容器都啟動并運行,就開始進行測試了。最后,測試結果和元數據存儲在Elasticsearch(ES)和S3中。我們用內部代理服務Apollo寫入ES。

如果你生活在一個分布式系統的世界,你一定無法避免主機故障。Seagull對任何實例故障都具有容錯功能。

例如,假設一個調度器要運行兩個包。Mesos會提供一個代理(A1)的資源給調度器。假設調度器認為資源充足,那么這兩個包會被安排在A1上。假如出于某種原因,A1出故障了,那么Mesos會通知到調度器。調度器的任務管理器決定重試或者丟棄那兩個包。如果重試,當Mesos下一次提供充分的資源(這種情況下,是提供代理A2的資源)時,那兩個包會被重新安排到時間計劃表里。為了防止包被丟棄,調度器會將那兩個包測試標記為“未執行”。

6. Seagull UI用Apollo從ES獲取結果,并將結果加載到UI供開發人員查看。如果結果全部通過,就可以準備配置了。

規模化挑戰

為了確保測試包的及時性,尤其是在高峰期,Seagull集群需要保證大量實例一直處于可用狀態。之前我們使用AWS的按需實例AWS ASGs,但對我們來說,要想達到這個容量成本太高了。

為了降低成本,我們開始使用一個叫FleetMiser的內部工具去維持Seagull集群。FleetMiser是一個用來測量基于不同信號的集群的自動縮放引擎,這些信號包括當前集群使用率、管道內的流量數等等。FleeMiser主要由以下兩部分組成:

  • AWS Spot Fleet:AWS有現場實例,現場實例比按需實例成本低很多,Spot Fleet能提供交互界面更簡單的現場實例。
  • 自動縮放:集群的使用時間不穩定,使用高峰主要集中在10:00-19:00(太平洋標準時間),此時,開發人員工作強度最大。為了動態調整范圍,FleetMiser使用集群在不同優先級別下的當前和歷史使用數據。Seagull集群每天的波動范圍大概介于1500CPU內核和10000CPU內核之間。

FleeMiser為我們的集群節省了大約80%的成本。在使用FleetMiser之前,我們是使用AWS按需實例,沒有自動縮放功能。

總結

Seagull使測試結果時長從2天縮短到了30分鐘,同時也大大降低了執行成本。從今以后,開發人員可以安心敲代碼,不用再花大量時間等待驗證變化卻束手無策。

 

來自:http://www.iteye.com/news/32424

 

 本文由用戶 Lerachee4a7u 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!