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

圖1 CS架構性能測試虛擬用戶腳本編寫解決方案
2)C/S架構通過二進制序列化的方式在客戶端與服務器端之間傳輸內存中的對象時只能先將報文反序列化為內存中的對象后再進行參數化;
3)選擇虛擬用戶腳本語言時需考慮工具支持的協(xié)議和腳本語言之間的關系以及所選擇的語言是否需要識別內存對象和組件;
4)當客戶端與服務器端之間傳輸的報文的數量和順序不固定時應考慮客戶端是否存在多線程或多進程同時發(fā)送報文。
結合實際測試項目開展了C/S架構系統(tǒng)性能測試虛擬用戶腳本編寫方法的技術研究,并對C/S架構系統(tǒng)性能測試虛擬用戶腳本編寫過程中遇到的問題和解決方法進行了描述。本次對C/S架構系統(tǒng)性能測試虛擬用戶腳本編寫技術的研究內容和結果總結如下:
1)當被測系統(tǒng)的客戶端與服務器端進行通信的報文是密文時可選擇讓系統(tǒng)開發(fā)方取消加密或調用加密解密組件或自行編寫加密解密算法的方式進行參數化;
2)當被測系統(tǒng)通過二進制序列化的方式在客戶端與服務器端之間傳輸內存中的對象時只能先將報文反序列化為內存中的對象后再進行參數化;
3)在選擇虛擬用戶腳本語言時需考慮測試工具支持的協(xié)議和腳本語言之間的關系以及所選擇的語言是否需要識別內存對象和組件;
4)當客戶端與服務器端之間傳輸的報文的數量和順序不固定時應考慮客戶端是否存在多線程或多進程同時發(fā)送報文;
5)C/S架構的系統(tǒng)在編寫虛擬用戶腳本時可通過對系統(tǒng)的業(yè)務邏輯的理解和系統(tǒng)開發(fā)方的協(xié)助查找出報文之間可能存在的復雜邏輯關系。