跑三小时的monkey测试该怎么算_百亿次的锤炼 - 带逛Dragonboat的各类测试
本文以近期開源的Dragonboat多組Raft庫為例,介紹Dragonboat這樣一個典型分布式系統(tǒng)是如何做測試的。Dragonboat以Go實現(xiàn),能在普通硬件上提供每秒1000萬次以上的強(qiáng)一致讀寫,它是目前github.com上速度最快的功能完整的多組Raft開源庫。歡迎大家試用,并請點Star支持:
lni/dragonboat?github.com最大的誤導(dǎo)
常看到有系統(tǒng)吹捧自己可靠的方法是說某大型活動用了它,或說是某某公司某內(nèi)部項目用了,從而得出可靠的結(jié)論,生產(chǎn)環(huán)境儼然成了廉價公關(guān)軟文口中的測試平臺。其實眾所周知,某活動全場意外當(dāng)機(jī)重啟的節(jié)點數(shù)少之又少,磁盤毀損一整年才2-4%,而故障性的網(wǎng)絡(luò)分區(qū)在很多DevOps崗的整個職業(yè)生涯里也就遇到幾次而已,以至于多年來各一線公司網(wǎng)絡(luò)分區(qū)造成故障的故事收集起來也才寫滿幾頁紙。某活動扛住了或是某項目用了,這些完全不是軟件可靠與否的充要條件。
事實其實是殘酷的。曾閱讀過國內(nèi)排名前四的某司一個共識庫,30分鐘代碼讀下來找到多處數(shù)據(jù)丟失毀損的bug,實現(xiàn)則是很典型的那種打死也不肯寫測試的全裸奔模式。
對于軟件,任何無法用代碼來驗證的廉價營銷式說辭,不說、不看、不聽相較于廉價的文宣,Dragonboat對系統(tǒng)正確性滿心敬畏,老老實實以完備的測試方案、開源的測試代碼、公開可驗證的測試結(jié)果數(shù)據(jù)三者來提供切實的保障。
常規(guī)測試
常規(guī)測試部分,Dragonboat做了:
- 數(shù)萬行全手寫測試代碼,Raft協(xié)議3000行核心代碼擁有過萬行測試代碼護(hù)航
- Go內(nèi)建的race detector測試
- 各類靜態(tài)檢查,及早發(fā)現(xiàn)如錯誤返回值未處理等可能問題
- 使用go-fuzz對所有網(wǎng)絡(luò)與本地輸入做隨機(jī)輸入fuzz測試
Dragonboat內(nèi)各Package覆蓋率基本均在90%以上。以Raft協(xié)議實現(xiàn)部分為例,基本不正確地刪改一行代碼就能觸發(fā)多個測試錯誤。這些測試代碼,連同下面要介紹的monkey testing,nightly build時在race detector被打開的情況下運(yùn)行。對于長期被人詬病的Golang的error處理方式,的確容易因為人為疏忽造成error返回有漏檢的可能,但僅gometalinter一個軟件收錄的靜態(tài)檢測工具就有多種能對付它。對各輸入的Fuzz testing初聽來或許有些多此一舉,但一跑Fuzz testing幾十秒就發(fā)現(xiàn)bug的例子比比皆是,Dragonboat開發(fā)中也曾遇到。
基于Raft協(xié)議的自測
Raft協(xié)議對內(nèi)部數(shù)據(jù)有嚴(yán)格限定要求,比如顯而易見的就有:
- 所有entry的Index值始終應(yīng)該是連續(xù)且嚴(yán)格遞增的
- 所有entry的Term值應(yīng)該是單向的
- 當(dāng)Index與Term確定時,entry內(nèi)容是唯一確定的
這些都提供較小代價下運(yùn)行時自測的機(jī)會。僅以第一項為例,在Dragonboat中它被落實到多個點位上,對應(yīng)用透明的進(jìn)行自測:
- 在節(jié)點完成了協(xié)議規(guī)定的檢查,即將append log時
- 在entry被commit以后,準(zhǔn)備由Raft協(xié)議返回供復(fù)制狀態(tài)機(jī)執(zhí)行時
- 復(fù)制狀態(tài)機(jī)即將執(zhí)行entry,由該entry Index對比當(dāng)前最新已執(zhí)行的entry的Index值時
這些自測在Dragonboat中無法通過任何設(shè)置予以關(guān)閉,甚至在Benchmark跑分時也嚴(yán)格限定必須進(jìn)行。
磁盤文件IO測試
磁盤文件IO要做正確有多難,可以先看兩個事實:
- Golang的標(biāo)準(zhǔn)庫在MacOS上默認(rèn)的使用,基本必然出現(xiàn)丟數(shù)據(jù)
- 專業(yè)測試顯示,包括git、leveldb、ZooKeeper等最著名項目,丟數(shù)據(jù)的bug曾有一堆
假設(shè)文件系統(tǒng)的可靠是天經(jīng)地義的吧?很遺憾,這種假設(shè)也是高危動作。
TS Pillai的這張總結(jié)圖表直觀顯示文件IO做正確有多難為解決這些磁盤文件IO的挑戰(zhàn),Dragonboat首先選擇不自作聰明的到處自己去做文件操作,把存儲盡可能交給RocksDB,并對基于RocksDB的系統(tǒng)加以各類測試:
- 使用ScyllaDB的charybdefs實現(xiàn)的磁盤錯誤注入測試
- 使用自動開關(guān)的掉電數(shù)據(jù)完整性測試
前者可以模擬諸如RocksDB試圖讀一個sst文件的內(nèi)容時第二次讀操作返回錯誤,幫助檢查Dragonboat是否按照設(shè)計正確地處理這樣的IO錯誤。掉電測試檢查fsync是否被正確配置(如MacOS上是否fcntl(fd, F_FULLFSYNC)了)與調(diào)用,是否IO邏輯上有丟數(shù)據(jù)的問題。
看了上述介紹,可能有人覺得這是小題大做,從Turbo C就開始玩的文件操作有啥難?hehe,文件操作方面是git、ZooKeeper的作者經(jīng)驗多,還是您更牛?
as we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknowns—the ones we don't know we don't know.Donald Rumsfeld
Monkey Testing
Monkey Testing有時也稱為Chaos Engineering,目的在于自動測試系統(tǒng)在各組件失效當(dāng)機(jī)情況下系統(tǒng)是否依舊能按設(shè)計提供應(yīng)有的服務(wù)。與Fuzz testing的隨機(jī)數(shù)據(jù)輸入不同,Monkey Testing / Chaos Engineering著眼于隨機(jī)破壞性事件對系統(tǒng)的影響。
Netflix提供了大量公開的資料,推廣Chaos Engineering在Dragonboat的monkey testing中,各種隨機(jī)破壞性事件的組合被注入到一個多節(jié)點的測試環(huán)境里,在一年多的自動測試期間,導(dǎo)致了百億數(shù)量級次數(shù)的Raft節(jié)點重啟事件,發(fā)現(xiàn)并修正了大量Raft協(xié)議實現(xiàn)與相關(guān)輔助功能的bug。具體的,在monkey testing中,被注入的隨機(jī)事件有:
- 隨意的停止各節(jié)點
- 隨意刪除節(jié)點所有Raft數(shù)據(jù)
- 隨意丟棄傳輸中的消息
- 隨意網(wǎng)絡(luò)分割節(jié)點暫時阻斷通訊
在上述大量注入的隨機(jī)破壞性事件前提下,同時在上述多節(jié)點測試環(huán)境上運(yùn)行大量Raft組實例,進(jìn)行Raft的讀寫測試。該monkey testing環(huán)境同時內(nèi)建一組三個節(jié)點的Drummer系統(tǒng),三個Drummer節(jié)點觀測、維護(hù)各Raft組健康信息,并在發(fā)現(xiàn)Raft組的成員失效以后,試圖在其它節(jié)點上通過Raft組成員變更,新增并啟動一個新的Raft成員,替換已失效的Raft成員。
上述三節(jié)點的Drummer本身也是一個基于Dragonboat的Raft實現(xiàn)的無單點系統(tǒng),且在monkey testing中同樣會被注入上述隨機(jī)錯誤。Drummer的上述監(jiān)控、修復(fù)Raft組的業(yè)務(wù)邏輯是在自身同樣面對大量被注入的隨機(jī)破壞性事件的前提下完成的,這進(jìn)一步驗證了此類具體實際業(yè)務(wù)邏輯下,Dragonboat的Raft實現(xiàn)的可靠性。
在一個節(jié)點平均存活僅幾分鐘的情況下,在幾臺服務(wù)器上每晚便可完成千萬次量級的節(jié)點隨機(jī)失效與重啟測試。在此及其嚴(yán)酷的測試環(huán)境中,同時向系統(tǒng)施加Raft讀寫請求,配合大量后臺的Raft快照保存與快照恢復(fù)操作,嚴(yán)格的后驗檢查確保:
- Jepsen的Knossos和porcupine檢查,絕無違反稱為linearizability的強(qiáng)一致性
- Raft組在有Quorum的時候需可用
- 用戶應(yīng)用狀態(tài)機(jī)狀態(tài)一致
- Raft組成員一致
- 磁盤上保存的Raft Entry Log一致
一部分Jepsen可讀格式的edn log已被公布,可供大家使用各自選定的Linearizability checker檢驗:
lni/knossos-data?github.com版權(quán)信息:
本文歡迎在不做任何修改刪節(jié)、保留完整原作者信息與出處的前提下合理轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的跑三小时的monkey测试该怎么算_百亿次的锤炼 - 带逛Dragonboat的各类测试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 演讲者模式投影到幕布也看到备注_家用投影
- 下一篇: c# vscode 配置_[VSCode