调度策略的测试方法及其自动化
背景介紹
隨著檢索端架構(gòu)日趨復(fù)雜,為了保證服務(wù)的高可用度,調(diào)度策略也在不斷地豐富完善。作為QA,我們需要關(guān)注調(diào)度測試:
? ※如何才能測得全面,保證無漏測?
? ※如何判斷策略對整個(gè)系統(tǒng)的影響?
? ※如何進(jìn)行自動(dòng)化,解放自己?
調(diào)度測試分析
首先,第一個(gè)問題,調(diào)度是什么?
?
圖1 游戲列車調(diào)度員截圖
網(wǎng)上有這么一個(gè)游戲:列車調(diào)度員。如圖1所示,游戲中,玩家會(huì)扮演列車調(diào)度員的角色,通過控制岔路口的軌道走向,讓每一輛列車可以成功地抵達(dá)目的地。
圍繞著這個(gè)目的,玩家需要思索:
? ※ 前方哪條路是正確的?
?? ※ 前方哪條路是通暢的?
? ?※前方哪條路上列車少?
? ?※前方突然出現(xiàn)事故了,怎么辦?
和列車調(diào)度員相似,我們設(shè)計(jì)了一系列調(diào)度策略來保證服務(wù)的高可用:
? ?※選擇正確的后端——解決了“前方哪條路是正確的?”的問題;
? ?※錯(cuò)誤檢測策略——解決了“前方哪條路是通暢的?”的問題;
? ?※負(fù)載均衡策略——解決了“前方哪條路上列車少?”的問題;
? ?※故障處理策略——解決了“前方突然出現(xiàn)事故”的問題。
第二個(gè)問題,調(diào)度怎么測?
給出一個(gè)具體的例子:“AC調(diào)度DX,重查時(shí)調(diào)度跨機(jī)房”,我們怎么測試這么一個(gè)典型的調(diào)度策略?
? ※首先,我們需要對策略進(jìn)行梳理,比如,A調(diào)度B,在哪些情況下會(huì)觸發(fā)重查?調(diào)度跨機(jī)房時(shí)有沒有開關(guān)控制?
? ※充分了解了策略的實(shí)現(xiàn)原理,可以進(jìn)行case設(shè)計(jì)了,那如何全面準(zhǔn)確地描述這個(gè)調(diào)度case,讓自己或他人在看到時(shí)能清晰地了解測試內(nèi)容呢?
? ※ 最后,便是case的執(zhí)行。如何高效地執(zhí)行這個(gè)調(diào)度case,如何在項(xiàng)目重提時(shí)很快地進(jìn)行回歸,是不是可以自動(dòng)化執(zhí)行?
從策略梳理,到case設(shè)計(jì),再到case執(zhí)行,我們的調(diào)度測試完成了嗎?
不!這些主要關(guān)注的是策略實(shí)現(xiàn)是否符合設(shè)計(jì),是否正確,屬于模塊級的調(diào)度測試。我們還需要關(guān)注策略對整個(gè)檢索端系統(tǒng)的影響,即策略是否合理。也就是說,我們還需要進(jìn)行系統(tǒng)級調(diào)度測試。
接下來,我將分別從模塊級和系統(tǒng)級兩個(gè)方面來分享我們的調(diào)度測試經(jīng)驗(yàn)。
模塊級調(diào)度測試
按照前面的講述,模塊級調(diào)度測試,可以分為三步:策略梳理、case設(shè)計(jì)、case執(zhí)行。
策略梳理
對于模塊級調(diào)度測試,需要解決的第一個(gè)問題便是策略梳理,有哪些調(diào)度策略,每個(gè)調(diào)度策略是如何實(shí)現(xiàn)的……
推薦通過代碼閱讀的方式來進(jìn)行策略梳理:
? ※RD的詳細(xì)設(shè)計(jì)往往不會(huì)很細(xì)致,無法兼顧到策略實(shí)現(xiàn)的所有細(xì)節(jié);
? ※調(diào)度的代碼實(shí)現(xiàn)和底層的socket管理密切相關(guān),存在一些容易出現(xiàn)問題的地方,而這些問題很多是測試難以cover的;
? ※檢索端模塊調(diào)度相關(guān)的代碼架構(gòu)比較清晰,而且和其他策略的耦合較少。
在代碼閱讀過程中,有幾點(diǎn)需要關(guān)注:
? ※需要關(guān)注socket連接的相關(guān)測試,包括socket建立、connect、listen、accept等函數(shù)的使用是否正確;
? ※需要關(guān)注函數(shù)的返回值,如函數(shù)內(nèi)各條分支在返回前是否正確地釋放了內(nèi)存、恢復(fù)了全局變量,函數(shù)在被調(diào)用時(shí)有沒有判斷返回值是否正常。
case設(shè)計(jì)
對策略深入了解和細(xì)致梳理后,進(jìn)行case設(shè)計(jì)時(shí),需要清晰把握構(gòu)建一個(gè)調(diào)度case的幾大要素,比如:
? ※被測模塊的配置:包括調(diào)度策略的開關(guān)、調(diào)度線程的數(shù)目、各種超時(shí)值的配置等;
? ※后端模塊的架構(gòu):后端有幾層機(jī)器每層有多少臺,亦或者有多少臺本機(jī)房多少臺跨機(jī)房;
? ※前端查詢狀態(tài):需要調(diào)度哪幾層機(jī)器,是首次調(diào)度還是重查調(diào)度;
? ※后端響應(yīng)狀態(tài):各后端機(jī)器的返回狀態(tài),是正常、超時(shí)、主動(dòng)斷開連接,還是返回結(jié)果包錯(cuò)誤;
? ※預(yù)期結(jié)果
? ·后端模塊接收到的請求包:是否應(yīng)該收到請求,收到的請求包中各字段取值是否正確,負(fù)載是否均衡;
? ·被測模塊返回的結(jié)果包:能否及時(shí)返回結(jié)果包,返回的結(jié)果包中各自段取值是否正確;
? ·被測模塊打印的日志:是否存在預(yù)期的特征日志。
在測試設(shè)計(jì)中,我們使用excel表格來記錄模塊級調(diào)度case,使整個(gè)case看起來更直觀準(zhǔn)確,如圖4所示:
?
圖4 使用excel記錄模塊級調(diào)度case
case執(zhí)行
我們借助一個(gè)中轉(zhuǎn)工具,實(shí)現(xiàn)了模塊級調(diào)度case的自動(dòng)化執(zhí)行,從而提高了測效率:
? ※被測模塊的配置和后端模塊的架構(gòu)——可以通過修改配置實(shí)現(xiàn)
? ※被測模塊打印的日志——可以通過日志解析實(shí)現(xiàn)
? ※前端的查詢以及后端的響應(yīng)——可以利用工具進(jìn)行網(wǎng)絡(luò)通信,以及后端各種網(wǎng)絡(luò)異常的模擬
? ※各模塊間數(shù)據(jù)包的處理——可以利用工具進(jìn)行數(shù)據(jù)包的解析和修改
我們實(shí)現(xiàn)了服務(wù)端對請求的各種請求:
? ※BREAK_AFTER_READ(后端接到請求后斷開連接)——在回調(diào)函數(shù)中,直接調(diào)用delete方法
? ※BREAK_WHEN_SEND(后端返回部分?jǐn)?shù)據(jù)后斷開連接)——在回調(diào)函數(shù)中,對將要返回的數(shù)據(jù)buf進(jìn)行切割得到sub_buf,調(diào)用send方法發(fā)送sub_buf后,調(diào)用delete方法
? ※CANNOT_CONNECT(后端無法連接)——調(diào)用stop方法
? ※CLOSE_AFTER_SEND(后端發(fā)送完正常數(shù)據(jù)后斷開連接)——在回調(diào)函數(shù)中,調(diào)用send方法發(fā)送完正常數(shù)據(jù)后,調(diào)用delete方法
? ※ERROR(后端不應(yīng)該接收到請求)——在回調(diào)函數(shù)中,收到請求時(shí)拋出異常
? ※INVALID_LENGTH(后端返回的mcpack包的長度無效)——在回調(diào)函數(shù)中,修改將要返回的mcpack包的長度為無效的數(shù)值,然后調(diào)用send方法發(fā)送數(shù)據(jù)包
? ※LACK_KEY(后端返回的mcpack包中缺少必選字段)——在回調(diào)函數(shù)中,調(diào)用預(yù)先準(zhǔn)備好的缺少必選字段的bft文件加載結(jié)果包,然后調(diào)用send方法發(fā)送數(shù)據(jù)包
? ※MORE_AFTER_SEND(后端發(fā)送完正常數(shù)據(jù)后再額外發(fā)送一段數(shù)據(jù))——在回調(diào)函數(shù)中,在將要返回的數(shù)據(jù)buf后拼接一段無用數(shù)據(jù),然后調(diào)用send方法發(fā)送數(shù)據(jù)包
? ※NORMAL(后端狀態(tài)正常)——在回調(diào)函數(shù)中,調(diào)用send方法發(fā)送正確的數(shù)據(jù)包
? ※RES_MINUS_ONE 、RES_MINUS_TWO 、RES_ONE 、RES_ZERO(后端返回response_code為-1、-2、1、0)——在回調(diào)函數(shù)中,修改將要返回的數(shù)據(jù)包的response_code為-1、-2、1、0,然后調(diào)用send方法發(fā)送數(shù)據(jù)包
? ※TIMEOUT(后端不返回?cái)?shù)據(jù),模擬黑洞)——在回調(diào)函數(shù)中,任何操作都不進(jìn)行
如圖5所示,一般一個(gè)模塊級調(diào)度case的自動(dòng)化執(zhí)行流程為:
? ※修改被測模塊的配置
? ※搭建后端模塊的架構(gòu)
? ※reload被測模塊使配置生效
? ※啟動(dòng)中轉(zhuǎn)工具模擬的各個(gè)后端服務(wù)端模塊
? ※啟動(dòng)中轉(zhuǎn)工具模擬的前端客戶端并發(fā)送查詢請求
? ※判斷結(jié)果是否符合預(yù)期
系統(tǒng)級調(diào)度測試
和模塊級調(diào)度不同,系統(tǒng)級調(diào)度測試的目的是測試策略對于系統(tǒng)是否有負(fù)面影響,即測試是否合理。
“策略對于系統(tǒng)是否有負(fù)面影響”?可以對這個(gè)問題進(jìn)行分解:
? ※既然是測試對系統(tǒng)的影響,那么系統(tǒng)架構(gòu)如何搭建?
? ※系統(tǒng)搭建好后,應(yīng)該構(gòu)造哪些場景,才能確保測試地全面?
? ※負(fù)面影響是什么影響,如何衡量,即如何判斷預(yù)期?
系統(tǒng)架構(gòu)
系統(tǒng)架構(gòu)當(dāng)然是越接近線上越好。但我們沒有和線上相同規(guī)模的測試機(jī)器,所以需要對線上架構(gòu)進(jìn)行簡化,抽取出影響調(diào)度測試的關(guān)鍵因素:
? ※需要有重查架構(gòu),即1個(gè)前端連接2個(gè)后端——因?yàn)樵谶@種架構(gòu)下,前端才會(huì)重查后端,而前端重查時(shí)很多調(diào)度策略都會(huì)發(fā)生變化;
? ※被測模塊需要連接多層后端,每層有多臺——因?yàn)橹贿B接1層、1臺的話,很多調(diào)度策略無法生效,后端根本無多余機(jī)器可供調(diào)度;
? ※本機(jī)房+跨機(jī)房——后端還存在本機(jī)房和跨機(jī)房之分,所以系統(tǒng)架構(gòu)中需要有本機(jī)房和跨機(jī)房;
其實(shí),這些架構(gòu)上的考慮都可以作為旁路環(huán)境部署的依據(jù),事實(shí)上,我們的系統(tǒng)級調(diào)度測試,都是復(fù)用旁路環(huán)境實(shí)現(xiàn)的。
場景設(shè)計(jì)
第二個(gè)問題,測試哪些場景?
在旁路環(huán)境中,是一直有流量的,可以看成是線上環(huán)境的一個(gè)縮影。
? ※首先,很容易想到需要模擬線上的基本運(yùn)維操作,確認(rèn)這些操作可以成功進(jìn)行:
? ·換庫
? ·換程序
? ·Reload操作
? ·架構(gòu)調(diào)整
? ※其次,需要關(guān)注出現(xiàn)各類異常時(shí),系統(tǒng)反應(yīng)是否符合預(yù)期:
? ·程序 dead
? ·網(wǎng)絡(luò)異常、傳輸速度慢
? ·程序不穩(wěn)定,頻繁出core,不斷重啟
? ※再次,可以為系統(tǒng)中各模塊隨機(jī)生成一系列狀態(tài),來觀察系統(tǒng)能否正常工作,從而增加系統(tǒng)級調(diào)度測試的覆蓋率。
基本預(yù)期
第三個(gè)問題,如何判斷預(yù)期?
由于是從系統(tǒng)級角度進(jìn)行測試,我們可以以用戶的姿態(tài)來觀察系統(tǒng)的運(yùn)行狀態(tài),即從最前端模塊來觀察效果:
? ※最前端模塊重查架構(gòu)下,沒有拒絕——如果出現(xiàn)拒絕,需要和RD確認(rèn);
? ※最前端模塊最終響應(yīng)時(shí)間不會(huì)超出用戶預(yù)期,如1.5秒。
除此之外,我們還需要關(guān)注各模塊有沒有出現(xiàn)異常報(bào)警,這里所謂的異常報(bào)警,包括本身正常但不應(yīng)該于此時(shí)出現(xiàn)的報(bào)警。
?【本文首發(fā)于:百度測試技術(shù)空間】http://hi.baidu.com/baiduqa/blog/item/27d83680e68df1ab6c811996.html
【關(guān)注百度技術(shù)沙龍】
?
轉(zhuǎn)載于:https://blog.51cto.com/baidutech/743207
與50位技術(shù)專家面對面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的调度策略的测试方法及其自动化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: I see IC的破冰之旅
- 下一篇: C/C++面试题:什么是COM和Acti