侯建華 黃兆森 房春榮 李良英
(1.珠海南方軟件網(wǎng)絡(luò)評測中心 珠海 519000)(2.南京慕測信息科技有限公司 南京 210000)
性能測試[1]的目的通常是評估被測軟件服務(wù)器端的性能,它通過性能測試腳本模擬大量客戶端同時(shí)對服務(wù)器端發(fā)起請求來測試服務(wù)器端的性能。
客戶端/服務(wù)器端的架構(gòu)一般可分為B/S架構(gòu)和C/S架構(gòu)。目前B/S架構(gòu)的系統(tǒng)比較流行,且B/S架構(gòu)的系統(tǒng)客戶端邏輯簡單,采用了標(biāo)準(zhǔn)協(xié)議,因此對B/S架構(gòu)的系統(tǒng)進(jìn)行性能測試腳本錄制就比較簡單。目前業(yè)界供參考的性能測試腳本錄制資料大部分都是針對B/S架構(gòu)系統(tǒng)的,缺乏針對C/S架構(gòu)系統(tǒng)的性能測試腳本錄制參考資料和案例。
C/S架構(gòu)性能測試腳本錄制或編寫通常會遇到加密或二進(jìn)制報(bào)文難以參數(shù)化、腳本無法識別內(nèi)存對象等問題。本文通過一個(gè)實(shí)際案例展示了解決這些問題的過程。
本文選取了某海關(guān)的客(貨)車通關(guān)管理系統(tǒng)作為研究案例,該系統(tǒng)主要用于海關(guān)人員對通關(guān)車輛和人員以及企業(yè)備案情況的核查和監(jiān)控。該系統(tǒng)為C/S架構(gòu),采用HTTP協(xié)議進(jìn)行通信,客戶端采用。NET開發(fā)技術(shù),使用C#語言開發(fā),客戶端存在復(fù)雜的業(yè)務(wù)邏輯,單個(gè)客戶端存在多線程與服務(wù)器端交互。服務(wù)器端采用Java開發(fā)技術(shù),通信內(nèi)容加密且進(jìn)行了二進(jìn)制序列化。這是一個(gè)非常具有挑戰(zhàn)性的性能測試項(xiàng)目,為進(jìn)一步提高評測中心性能測試的技術(shù)能力,評測中心利用該項(xiàng)目開展了一系列針對C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本編寫方法的技術(shù)研究,解決了C/S架構(gòu)性能測試腳本錄制或編寫遇到的加密或二進(jìn)制報(bào)文難以參數(shù)化、腳本無法識別內(nèi)存對象等問題。
C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本的編寫與B/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本的編寫一樣主要包括兩個(gè)步驟,即虛擬用戶腳本錄制和虛擬用戶腳本的參數(shù)化[2]。但C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本在編寫過程中會遇到許多特有的問題,本案例在編寫虛擬用戶腳本時(shí)遇到了5個(gè)問題:
1)當(dāng)被測系統(tǒng)的客戶端與服務(wù)器端進(jìn)行通信的報(bào)文是密文時(shí),如何對報(bào)文進(jìn)行參數(shù)化;
2)當(dāng)被測系統(tǒng)通過二進(jìn)制序列化的方式在客戶端與服務(wù)器端之間傳輸內(nèi)存中的對象時(shí),如何對傳輸?shù)膶ο筮M(jìn)行參數(shù)化;
3)如何確定要編寫的虛擬用戶腳本的語言;
4)當(dāng)客戶端與服務(wù)器端之間傳輸?shù)膱?bào)文的數(shù)量和順序不固定時(shí),如何確定性能測試時(shí)要發(fā)送哪些報(bào)文;
5)如何模擬胖客戶端的業(yè)務(wù)邏輯。
3.2.1 密文報(bào)文的參數(shù)化
本文的案例采用的是HTTP協(xié)議,筆者采用HP Loadrunner工具[3]選擇HTTP協(xié)議錄制該C/S架構(gòu)系統(tǒng)的虛擬用戶腳本[4],發(fā)現(xiàn)錄制的腳本中客戶端與服務(wù)器端進(jìn)行通信的報(bào)文是密文,性能測試技術(shù)人員無法理解報(bào)文,進(jìn)而導(dǎo)致無法對報(bào)文進(jìn)行參數(shù)化。該問題有四種解決方法:
1)若加密解密操作消耗的系統(tǒng)資源少,對系統(tǒng)性能影響不大,則可以忽略加密解密操作對性能測試結(jié)果的影響,由系統(tǒng)開發(fā)方協(xié)助提供一個(gè)未采用加密技術(shù)的相同系統(tǒng)進(jìn)行性能測試;
2)由系統(tǒng)開發(fā)方將加密解密方法封裝成組件提供給測試方,并告知測試方組件的使用方法,測試方在虛擬用戶腳本中調(diào)用組件進(jìn)行加密解密操作[5];
3)測試方在虛擬用戶腳本中調(diào)用相同加密解密算法的第三方組件進(jìn)行加密解密操作;
4)在虛擬用戶腳本中自行編寫加密解密算法代碼。
由于被測系統(tǒng)的加密解密操作對系統(tǒng)性能影響不大,本次性能測試采取了第一種措施解決了該系統(tǒng)的報(bào)文加密問題。
3.2.2 二進(jìn)制報(bào)文的參數(shù)化
成功解決通訊報(bào)文為密文的問題后,再次對該C/S架構(gòu)系統(tǒng)錄制了腳本,但腳本中仍然存在部分人工不可讀的內(nèi)容。經(jīng)與該C/S架構(gòu)系統(tǒng)的軟件開發(fā)方技術(shù)人員進(jìn)行溝通,確認(rèn)這些內(nèi)容為采用二進(jìn)制序列化方式傳輸?shù)膬?nèi)存對象。
當(dāng)被測系統(tǒng)通過二進(jìn)制序列化的方式在客戶端與服務(wù)器端之間傳輸內(nèi)存中的對象時(shí),性能測試技術(shù)人員無法理解二進(jìn)制的對象內(nèi)容,因此無法直接對報(bào)文中的二進(jìn)制對象進(jìn)行參數(shù)化。為解決此問題,筆者首先考慮了讓系統(tǒng)開發(fā)方協(xié)助將被測系統(tǒng)改為采用XML方式進(jìn)行序列化的方法,這種方法雖然可以使序列化后產(chǎn)生的數(shù)據(jù)流報(bào)文可讀,但會對被測系統(tǒng)的性能產(chǎn)生較大影響,導(dǎo)致性能測試的結(jié)果與實(shí)際系統(tǒng)性能相差較大,因此,筆者最終否定了這種方法。為了能夠進(jìn)行參數(shù)化又同時(shí)不對性能測試結(jié)果產(chǎn)生太大的影響,本次性能測試只能在虛擬用戶腳本中對數(shù)據(jù)流報(bào)文先進(jìn)行反序列化操作,使報(bào)文轉(zhuǎn)化為可讀的內(nèi)存中的對象,再對內(nèi)存中的對象進(jìn)行參數(shù)化。
3.2.3 虛擬用戶腳本語言的選擇
在HP Loadrunner中選擇HTTP協(xié)議錄制腳本時(shí)只支持C語言的虛擬用戶腳本[6],但該C/S架構(gòu)系統(tǒng)的客戶端采用的是C#語言對內(nèi)存對象進(jìn)行了二進(jìn)制序列化和反序列化,若采用C語言的虛擬用戶腳本,難以對該二進(jìn)制數(shù)據(jù)流報(bào)文進(jìn)行序列化和反序列化操作,也難以識別反序列化后的內(nèi)存對象,導(dǎo)致無法對反序列化后的內(nèi)存對象進(jìn)行參數(shù)化[7]。因此,本次性能測試不能選擇C語言作為虛擬用戶腳本語言。
在選擇虛擬用戶腳本語言時(shí)需考慮以下三方面的內(nèi)容:
1)如果需要利用性能測試工具通過錄制腳本的方式產(chǎn)生虛擬用戶腳本,首先要選擇通訊協(xié)議,然后選擇該通訊協(xié)議支持的腳本語言;
2)如果需要對特定語言的內(nèi)存對象進(jìn)行參數(shù)化,必須選擇能夠識別該內(nèi)存對象的虛擬用戶腳本語言;
3)如果需要調(diào)用客戶端的組件,必須選擇能夠識別該組件的虛擬用戶腳本語言。
經(jīng)過仔細(xì)的分析和比較,筆者最終選擇了支持識別。NET內(nèi)存對象的C#語言作為虛擬用戶腳本語言[8]。由于HP Loadrunner的HTTP協(xié)議不支持C#語言腳本的錄制,只能采用人工編寫C#語言虛擬用戶腳本,模擬C/S架構(gòu)系統(tǒng)的客戶端發(fā)送和處理HTTP報(bào)文。
3.2.4 多線程報(bào)文的處理
筆者根據(jù)該C/S架構(gòu)系統(tǒng)的業(yè)務(wù)特點(diǎn)和技術(shù)特點(diǎn)對業(yè)務(wù)數(shù)據(jù)和技術(shù)數(shù)據(jù)進(jìn)行參數(shù)化操作[9],為盡快查找需要參數(shù)化的數(shù)據(jù),筆者再次抓取了該C/S架構(gòu)系統(tǒng)客戶端與服務(wù)器端進(jìn)行交互的報(bào)文,并將兩次抓取的報(bào)文進(jìn)行了對比,結(jié)果發(fā)現(xiàn)客戶端與服務(wù)器端之間傳輸?shù)膱?bào)文的數(shù)量和順序是不固定的。
當(dāng)出現(xiàn)這種情況時(shí),性能測試的技術(shù)人員就容易被報(bào)文所困擾,因?yàn)椴恢涝趫?zhí)行測試時(shí)應(yīng)該如何發(fā)送報(bào)文。此時(shí)應(yīng)分析出現(xiàn)這種情況的原因,經(jīng)過與系統(tǒng)開發(fā)方相關(guān)人員進(jìn)行溝通得知,被測系統(tǒng)為了維持會話狀態(tài),客戶端有一線程每隔一段時(shí)間就會向服務(wù)器端發(fā)送一個(gè)心跳報(bào)文,所以導(dǎo)致捕捉的報(bào)文的數(shù)量和順序不固定。由于心跳報(bào)文與業(yè)務(wù)操作無關(guān),因此可將心跳報(bào)文過濾后再對業(yè)務(wù)操作產(chǎn)生的報(bào)文進(jìn)行參數(shù)化。在發(fā)送報(bào)文時(shí)也可以像真實(shí)客戶端一樣采用多線程技術(shù)每隔一段時(shí)間發(fā)送一個(gè)心跳報(bào)文。
3.2.5 客戶端業(yè)務(wù)邏輯的模擬
C/S架構(gòu)系統(tǒng)的客戶端是胖客戶端,因此,不可避免地會在客戶端包含業(yè)務(wù)邏輯[10]。性能測試要在虛擬用戶腳本中模擬客戶端發(fā)送報(bào)文,如果客戶端包含業(yè)務(wù)邏輯,則服務(wù)器端的返回報(bào)文和客戶端隨后發(fā)送的報(bào)文之間可能就會存在較復(fù)雜的邏輯關(guān)系。
性能測試技術(shù)人員只能看到報(bào)文,無法看到報(bào)文在客戶端是如何進(jìn)行計(jì)算處理的。當(dāng)需要從返回報(bào)文中提取數(shù)據(jù),再對即將發(fā)送的報(bào)文進(jìn)行參數(shù)化時(shí),只有正確分析出這些報(bào)文之間的邏輯關(guān)系才能在虛擬用戶腳本中正確地模擬系統(tǒng)客戶端進(jìn)行業(yè)務(wù)操作。
該C/S架構(gòu)系統(tǒng)的客戶端就存在業(yè)務(wù)邏輯,筆者通過對系統(tǒng)的業(yè)務(wù)邏輯的理解和系統(tǒng)開發(fā)方的協(xié)助,完成了虛擬用戶腳本的參數(shù)化,且成功回放了參數(shù)化后的虛擬用戶腳本,對應(yīng)的業(yè)務(wù)操作也已生效。
通過對本案例遇到的問題和解決方法進(jìn)行梳理,可形成C/S架構(gòu)性能測試虛擬用戶腳本編寫的解決方案,見圖1。
本解決方案主要共享如下:
1)C/S架構(gòu)的客戶端與服務(wù)器端進(jìn)行通信的報(bào)文是密文時(shí),可選擇取消加密或調(diào)用加密解密組件或自行編寫加密解密算法的方法進(jìn)行參數(shù)化;
圖1 CS架構(gòu)性能測試虛擬用戶腳本編寫解決方案
2)C/S架構(gòu)通過二進(jìn)制序列化的方式在客戶端與服務(wù)器端之間傳輸內(nèi)存中的對象時(shí)只能先將報(bào)文反序列化為內(nèi)存中的對象后再進(jìn)行參數(shù)化;
3)選擇虛擬用戶腳本語言時(shí)需考慮工具支持的協(xié)議和腳本語言之間的關(guān)系以及所選擇的語言是否需要識別內(nèi)存對象和組件;
4)當(dāng)客戶端與服務(wù)器端之間傳輸?shù)膱?bào)文的數(shù)量和順序不固定時(shí)應(yīng)考慮客戶端是否存在多線程或多進(jìn)程同時(shí)發(fā)送報(bào)文。
結(jié)合實(shí)際測試項(xiàng)目開展了C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本編寫方法的技術(shù)研究,并對C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本編寫過程中遇到的問題和解決方法進(jìn)行了描述。本次對C/S架構(gòu)系統(tǒng)性能測試虛擬用戶腳本編寫技術(shù)的研究內(nèi)容和結(jié)果總結(jié)如下:
1)當(dāng)被測系統(tǒng)的客戶端與服務(wù)器端進(jìn)行通信的報(bào)文是密文時(shí)可選擇讓系統(tǒng)開發(fā)方取消加密或調(diào)用加密解密組件或自行編寫加密解密算法的方式進(jìn)行參數(shù)化;
2)當(dāng)被測系統(tǒng)通過二進(jìn)制序列化的方式在客戶端與服務(wù)器端之間傳輸內(nèi)存中的對象時(shí)只能先將報(bào)文反序列化為內(nèi)存中的對象后再進(jìn)行參數(shù)化;
3)在選擇虛擬用戶腳本語言時(shí)需考慮測試工具支持的協(xié)議和腳本語言之間的關(guān)系以及所選擇的語言是否需要識別內(nèi)存對象和組件;
4)當(dāng)客戶端與服務(wù)器端之間傳輸?shù)膱?bào)文的數(shù)量和順序不固定時(shí)應(yīng)考慮客戶端是否存在多線程或多進(jìn)程同時(shí)發(fā)送報(bào)文;
5)C/S架構(gòu)的系統(tǒng)在編寫虛擬用戶腳本時(shí)可通過對系統(tǒng)的業(yè)務(wù)邏輯的理解和系統(tǒng)開發(fā)方的協(xié)助查找出報(bào)文之間可能存在的復(fù)雜邏輯關(guān)系。