大規(guī)模分布式系統(tǒng)的測(cè)試實(shí)踐
1. 飛天測(cè)試的挑戰(zhàn)
飛天開(kāi)放平臺(tái)基于一個(gè)核心系統(tǒng),即飛天大規(guī)模分布式計(jì)算系統(tǒng)(簡(jiǎn)稱飛天)。飛天期望把幾千臺(tái)PC構(gòu)成一臺(tái)“超級(jí)計(jì)算機(jī)”,給上層多種不同的開(kāi)放服務(wù)和云應(yīng)用提供通用的分布式存儲(chǔ)、計(jì)算和任務(wù)調(diào)度等多重功能??梢钥闯?,飛天具有平臺(tái)化,通用性和大規(guī)模的特性,飛天測(cè)試的挑戰(zhàn)也由此而來(lái)。
挑戰(zhàn)一:平臺(tái)軟件的復(fù)雜性和互聯(lián)網(wǎng)發(fā)布節(jié)奏之間的矛盾。 飛天包含多個(gè)復(fù)雜的分布式模塊。模塊本身的復(fù)雜性乘上各模塊之間的協(xié)議依賴,按照傳統(tǒng)軟件開(kāi)發(fā)流程計(jì)算,發(fā)布一個(gè)質(zhì)量可靠的穩(wěn)定版本通常需要1~2年。 這樣的發(fā)布節(jié)奏遠(yuǎn)遠(yuǎn)滿足不了上層開(kāi)放服務(wù)和云應(yīng)用快速發(fā)展的需要。
挑戰(zhàn)二: 通用平臺(tái)支持多種不同應(yīng)用帶來(lái)測(cè)試用例數(shù)的爆炸。對(duì)于飛天,不同的應(yīng)用場(chǎng)景,不同的數(shù)據(jù)量,不同的請(qǐng)求壓力,不同的機(jī)器規(guī)模,有可能在代碼里面走的路徑完全不一樣,對(duì)系統(tǒng)的壓力點(diǎn)也各不相同。無(wú)論是試圖覆蓋所有應(yīng)用對(duì)飛天的所有用法,還是從設(shè)計(jì)出發(fā)遍歷模塊接口的各種組合,對(duì)測(cè)試用例設(shè)計(jì)而言都是不收斂的。那么,當(dāng)測(cè)試用例剪枝無(wú)門,是否還有其他捷徑?
挑戰(zhàn)三:大規(guī)模生產(chǎn)集群上的問(wèn)題如何用小規(guī)模測(cè)試集群暴露。 在阿里各地的數(shù)據(jù)中心,飛天的生產(chǎn)集群是上千臺(tái)物理機(jī)組成的??紤]到成本,測(cè)試集群規(guī)模通常不超過(guò)生產(chǎn)集群的十分之一。統(tǒng)計(jì)數(shù)據(jù)顯示,100臺(tái)和1000臺(tái)的分布式環(huán)境的軟硬件故障率,壓力瓶頸點(diǎn),數(shù)據(jù)量級(jí),網(wǎng)絡(luò)性能都會(huì)有很大差異。常規(guī)測(cè)試方法很難在小集群上發(fā)現(xiàn)大規(guī)模的問(wèn)題
下面,我們來(lái)談一下飛天測(cè)試實(shí)踐當(dāng)前是如何應(yīng)對(duì)這三種挑戰(zhàn)的。
2. 分層測(cè)試和持續(xù)集成
目前,飛天底層模塊的發(fā)布節(jié)奏是半年一次,上層模塊的發(fā)布則更為頻繁,最短可以達(dá)到三周發(fā)布一次。這樣的發(fā)布節(jié)奏主要依靠分層測(cè)試和持續(xù)集成的機(jī)制。按測(cè)試層次來(lái)分,飛天測(cè)試可以分為單元測(cè)試,功能測(cè)試,系統(tǒng)測(cè)試,集成測(cè)試,E2E測(cè)試(端到端測(cè)試)。為了加速飛天新版本的質(zhì)量收斂,飛天團(tuán)隊(duì)幾乎每個(gè)成員都會(huì)參與到上述測(cè)試類型中,無(wú)論是開(kāi)發(fā)同學(xué),還是測(cè)試同學(xué)。
一般來(lái)說(shuō),產(chǎn)品只會(huì)對(duì)外部接口進(jìn)行功能測(cè)試和系統(tǒng)測(cè)試,但是由于飛天模塊本身就是分布式的,每個(gè)模塊都具有了一個(gè)傳統(tǒng)軟件產(chǎn)品的復(fù)雜度。所以,模塊團(tuán)隊(duì)除了負(fù)責(zé)單元測(cè)試,也會(huì)進(jìn)行功能測(cè)試和系統(tǒng)測(cè)試。模塊團(tuán)隊(duì)內(nèi),開(kāi)發(fā)同學(xué)負(fù)責(zé)單元測(cè)試之外,還會(huì)承擔(dān)功能測(cè)試和局部特性的系統(tǒng)測(cè)試, 測(cè)試同學(xué)通常更專注在測(cè)試設(shè)計(jì)和模塊級(jí)別的系統(tǒng)測(cè)試。
飛天有獨(dú)立于模塊的集成測(cè)試團(tuán)隊(duì),集成測(cè)試主要負(fù)責(zé)兩塊。一方面,通過(guò)持續(xù)集成的回歸測(cè)試集來(lái)保證系統(tǒng)中的各個(gè)模塊改動(dòng)集成在一起能夠很好的工作,一旦發(fā)現(xiàn)無(wú)法短期修復(fù)的質(zhì)量回退,模塊改動(dòng)會(huì)被立刻關(guān)閉或回滾。為保證持續(xù)集成效果,不同層次的回歸測(cè)試集都被盡可能自動(dòng)化和并且定義合適的回歸頻率, 模塊改動(dòng)在設(shè)計(jì)時(shí)也會(huì)考慮方便關(guān)閉或回滾。 另一方面,集成測(cè)試也進(jìn)行平臺(tái)級(jí)別的系統(tǒng)測(cè)試,極盡所能對(duì)飛天進(jìn)行各種嚴(yán)刑拷打,考察底層模塊的功能,性能和系統(tǒng)容量,以及在極端或典型應(yīng)用場(chǎng)景下系統(tǒng)的穩(wěn)定性和服務(wù)可用性。
飛天新版本上線前,開(kāi)放服務(wù)團(tuán)隊(duì)一般都會(huì)用集成測(cè)試通過(guò)的版本跑E2E測(cè)試。E2E測(cè)試的責(zé)任人需負(fù)責(zé)向應(yīng)用方了解具體需求,這個(gè)需求不僅是一個(gè)對(duì)接口功能的需求,還包含了數(shù)據(jù)量的需求,機(jī)器規(guī)模的需求,吞吐率的需求,延遲時(shí)間的需求,以及業(yè)務(wù)量在一天或者一周內(nèi)的曲線等等信息。E2E 測(cè)試通常要構(gòu)造近乎完整的應(yīng)用場(chǎng)景,盡可能模擬/重現(xiàn)真實(shí)的數(shù)據(jù)情況和壓力特征,并且要通過(guò)長(zhǎng)時(shí)間的穩(wěn)定性測(cè)試。有些上層應(yīng)用還會(huì)常備試運(yùn)行環(huán)境(Staging Environment)來(lái)隨時(shí)做E2E測(cè)試的驗(yàn)證。通常,我們只有在通過(guò)了最后的E2E測(cè)試之后才能上線給應(yīng)用生產(chǎn)集群。
為保證測(cè)試本身的質(zhì)量,各層測(cè)試覆蓋有不同的衡量方法。單元測(cè)試用Coverage工具來(lái)檢驗(yàn)行覆蓋和分支覆蓋;功能測(cè)試一般考察功能點(diǎn)覆蓋外,這些都是大家熟知的。此外,我們對(duì)系統(tǒng)測(cè)試,集成測(cè)試和E2E測(cè)試設(shè)計(jì)了一種特別的覆蓋- Log Coverage。Log Coverage工具能夠通過(guò)測(cè)試運(yùn)行過(guò)程中飛天輸出的Log信息的多少來(lái)判斷測(cè)試是否有足夠的覆蓋率。通過(guò)拿到生產(chǎn)集群的Log與測(cè)試中的Log進(jìn)行比較,會(huì)找到我們之前沒(méi)有測(cè)試到的地方。另外,通過(guò)對(duì)代碼中從未打印出的Error Log的檢查,我們也可以知道有多少異常邏輯我們沒(méi)有測(cè)試過(guò)。
3.基于監(jiān)控的探索性測(cè)試和灰盒測(cè)試
如挑戰(zhàn)二所述,測(cè)試用例的爆炸一度讓我們非常糾結(jié)。我們發(fā)現(xiàn)無(wú)法通過(guò)黑盒測(cè)試的設(shè)計(jì)思路來(lái)窮舉所有的情況,即使能設(shè)計(jì)出足夠完整的測(cè)試用例,我們也沒(méi)有足夠機(jī)器,人手和時(shí)間來(lái)執(zhí)行這些測(cè)試。
所幸,我們還有探索性測(cè)試,監(jiān)控系統(tǒng)則成為我們探索方向的指引。飛天有詳細(xì)的監(jiān)控系統(tǒng)可以監(jiān)控整個(gè)集群的各種參數(shù),這些參數(shù)不光是OS層面的參數(shù),更多的是飛天模塊本身通過(guò)調(diào)用我們監(jiān)控系統(tǒng)的API來(lái)完成對(duì)自身某些指標(biāo)的統(tǒng)計(jì)。這些統(tǒng)計(jì)不光在線上系統(tǒng)能夠起到監(jiān)控報(bào)警的作用,也能給探索性測(cè)試提供依據(jù)。執(zhí)行測(cè)試的人員可以通過(guò)不斷改變測(cè)試的各項(xiàng)參數(shù),結(jié)合這些指標(biāo)的變化進(jìn)行探索式的測(cè)試,一個(gè)壓力測(cè)試用例在執(zhí)行時(shí)可以變化出貼近應(yīng)用的各種極端場(chǎng)景。通常,通過(guò)指標(biāo)在某些壓力變化下或者隨著時(shí)間推移時(shí)的異常行為,測(cè)試人員會(huì)更容易找到一些深藏的Bug。另外,在平臺(tái)級(jí)別的系統(tǒng)測(cè)試時(shí),通過(guò)對(duì)模塊內(nèi)部Error Log的監(jiān)控也能達(dá)到很好的效果。
探索性測(cè)試固然重要,但是光有探索,如果測(cè)試人員本身不了解系統(tǒng)的一些內(nèi)部邏輯,會(huì)出現(xiàn)兩種情況:第一種是,只驗(yàn)證設(shè)計(jì)好的場(chǎng)景,其他一些異常的情況,自己無(wú)法解釋,但是本身又不是驗(yàn)證標(biāo)準(zhǔn),導(dǎo)致很多隱藏的問(wèn)題最終在線上爆發(fā);第二種是,像一個(gè)無(wú)頭蒼蠅,漫無(wú)目的的進(jìn)行探索,浪費(fèi)了時(shí)間,卻達(dá)不到好的效果。在飛天測(cè)試中,我們要求測(cè)試人員必須從方案設(shè)計(jì)之初甚至是討論需求的時(shí)候就和開(kāi)發(fā)的同學(xué)在一起討論,測(cè)試的同學(xué)需要比開(kāi)發(fā)更加理解系統(tǒng)的設(shè)計(jì)原則。
了解分布式系統(tǒng)的工作原理后,測(cè)試同學(xué)會(huì)明白如何去做一個(gè)有效的灰盒測(cè)試。比如,在某個(gè)關(guān)鍵點(diǎn)加請(qǐng)求壓力會(huì)事半功倍;在哪個(gè)時(shí)機(jī)去做測(cè)試結(jié)果斷言會(huì)更方便,徹底或完整;甚至知道對(duì)一個(gè)模塊進(jìn)程如何注入代碼,模擬重現(xiàn)機(jī)率很小的協(xié)議通信丟包的問(wèn)題。
有一個(gè)很典型的例子,早期,我們內(nèi)部開(kāi)發(fā)一個(gè)基于表結(jié)構(gòu)的存儲(chǔ)引擎時(shí),曾經(jīng)出現(xiàn)過(guò)這樣一件事情:測(cè)試程序在最終驗(yàn)證一致性時(shí),一直都是通過(guò)的,但是業(yè)務(wù)方和我們一起做E2E測(cè)試的時(shí)候,會(huì)有很低的概率發(fā)現(xiàn)數(shù)據(jù)讀出來(lái)是錯(cuò)誤的。測(cè)試人員百思不得其解,最后發(fā)現(xiàn),這份數(shù)據(jù)在寫入的時(shí)候,會(huì)先在三個(gè)地方進(jìn)行修改,但是由于一些時(shí)序和鎖的問(wèn)題,在改過(guò)了兩個(gè)地方之后就返回成功了,第三個(gè)地方是在內(nèi)存中,過(guò)一陣子就會(huì)被重新刷成正確的值。如果當(dāng)時(shí)測(cè)試的同學(xué)知道系統(tǒng)里面這些設(shè)計(jì),當(dāng)時(shí)就會(huì)設(shè)計(jì)寫入過(guò)程中,對(duì)數(shù)據(jù)一致性進(jìn)行實(shí)時(shí)檢測(cè),就不會(huì)在代價(jià)更高的E2E測(cè)試中發(fā)現(xiàn)問(wèn)題,解決的效率也會(huì)因此而提高。
4. 帶壓力和隨機(jī)故障模擬的長(zhǎng)時(shí)間穩(wěn)定性測(cè)試
文首提到大規(guī)模生產(chǎn)集群上的問(wèn)題,很難在小規(guī)模的測(cè)試集群上發(fā)現(xiàn)。究其原因,我們發(fā)現(xiàn)主要是兩方面導(dǎo)致的:
1. 大規(guī)模集群中原本小概率的單機(jī)故障會(huì)隨機(jī)器數(shù)增加,導(dǎo)致集群整體的硬件故障率線性提升,甚至多種故障同時(shí)發(fā)生的概率也大大增加。
2. 機(jī)器數(shù)增多會(huì)導(dǎo)致對(duì)飛天模塊的壓力點(diǎn)發(fā)生轉(zhuǎn)移。以彈性計(jì)算(ECS)為例,在300臺(tái)變600臺(tái)時(shí)發(fā)現(xiàn),原本擔(dān)心的文件系統(tǒng)master還未成為QPS瓶頸,負(fù)責(zé)鎖文件協(xié)同的命名服務(wù)首先成為瓶頸。
此外,各種故障的組合爆炸也讓完整的容錯(cuò)測(cè)試在設(shè)計(jì)和執(zhí)行上的代價(jià)變得太大。
為解決上述困難,在飛天測(cè)試實(shí)踐中,我們逐漸積累出一套帶背景壓力和隨機(jī)故障模擬的長(zhǎng)時(shí)間穩(wěn)定性測(cè)試方案。
背景壓力主要是針對(duì)各個(gè)底層模塊的讀寫壓力,通常會(huì)針對(duì)某類應(yīng)用場(chǎng)景來(lái)模擬?;诜侄沃拖到y(tǒng)仿真的方法, 我們實(shí)現(xiàn)了一些輕量級(jí)的壓力工具,讓各模塊的master機(jī)器和slave機(jī)器分別接受到大規(guī)模生產(chǎn)集群上的類似訪問(wèn)壓力和連接規(guī)模。另外,還增加一些諸如CPU,Memory,Network的資源消耗器,以模擬生產(chǎn)環(huán)境業(yè)務(wù)繁忙導(dǎo)致機(jī)器資源緊張場(chǎng)景。故障模擬上,一方面盡可能豐富軟件手段模擬軟硬件故障,比如磁盤錯(cuò)誤(包括壞盤,只讀等),機(jī)器宕機(jī),重啟,斷網(wǎng),交換機(jī)重啟,主要模塊進(jìn)程重啟,假死等;另一方面,這些故障模擬操作都會(huì)按照預(yù)先設(shè)定比例進(jìn)行隨機(jī)組合。在這樣的背景壓力和隨機(jī)故障操作下,長(zhǎng)時(shí)間(至少7x24 小時(shí))持續(xù)運(yùn)行上層應(yīng)用模擬程序/作業(yè),同時(shí)通過(guò)在線監(jiān)控系統(tǒng)來(lái)檢查飛天是否正常。
簡(jiǎn)而言之,我們用背景壓力解決壓力點(diǎn)問(wèn)題,用長(zhǎng)時(shí)間跑解決小集群的故障小概率問(wèn)題,用隨機(jī)故障模擬和組合來(lái)解決容錯(cuò)測(cè)試設(shè)計(jì)和執(zhí)行的代價(jià)問(wèn)題。
實(shí)踐證明,飛天很多重要的bug都是通過(guò)這個(gè)測(cè)試被發(fā)現(xiàn)的。當(dāng)然這類測(cè)試也有短處,就是問(wèn)題調(diào)查需要較長(zhǎng)的時(shí)間,要求測(cè)試人員對(duì)系統(tǒng)有較深的了解和診斷能力。
5. 結(jié)束語(yǔ)
大規(guī)模分布式系統(tǒng)的測(cè)試是一項(xiàng)非常有挑戰(zhàn)的工作。 盡管我們持續(xù)落實(shí)各層測(cè)試,積累實(shí)踐經(jīng)驗(yàn),創(chuàng)新測(cè)試方法,但由于測(cè)試條件的限制,生產(chǎn)環(huán)境的復(fù)雜,軟件問(wèn)題仍然無(wú)法完全依賴測(cè)試消除。本文僅僅提到了飛天測(cè)試在Test in lab方向的一些思考和實(shí)踐,完善的飛天質(zhì)量保證體系其實(shí)需要Test in Lab和Test in Production雙管齊下,這是飛天測(cè)試樂(lè)此不疲的努力方向。