孫 立 哲
(公安部第三研究所eID事業部 上海 201204)
隨著計算機網絡的快速發展,網絡用戶數增多,并發訪問量加大,分布式應用系統在高并發可用性方面面臨巨大的挑戰。為了提高系統的高并發性能,分布式應用系統內部設計多采用異步處理模式。隨著互聯網應用技術復雜性不斷提高,高效的測試技術和工具逐漸成為高質量應用的必要保證。
HTTP接口即基于HTTP協議、可遠程訪問的接口,是分布式應用系統[1]的一種技術實現。HTTP協議是互聯網上客戶端瀏覽器或其他程序與Web服務器之間的應用層通信協議[2]。接口是預先定義的函數,旨在提供應用程序與開發人員基于某軟件或硬件得以訪問一組例程的能力。接口內部實現對特定業務處理邏輯的封裝,接口調用方只需按接口調用規則進行訪問即可完成特定業務的處理,無需關注內部實現細節。
根據接口內部業務處理模式不同,HTTP接口可分為同步接口和異步接口。同步接口是指請求方以HTTP請求方式訪問服務端HTTP接口,接口收到請求并完成全部業務處理后將結果以HTTP響應方式直接返回給請求方。異步接口是指請求方以HTTP請求方式訪問服務端HTTP異步接口,請求參數中需包含一個用于接收異步處理結果的HTTP回調接口地址,接口收到請求并在完成部分業務處理后以HTTP響應方式將處理結果返回給請求方(即同步返回),或者不做任何業務處理直接以HTTP響應方式返回一定數據以告知請求已收到,之后HTTP接口內部再啟動新線程處理后續業務并訪問請求方提供的回調接口將結果發給請求方(即異步返回)。HTTP異步接口業務流程圖如圖1所示。

圖1 HTTP異步接口的業務處理流程圖
JMeter[3]是Apache組織開發的基于Java的壓力測試工具,以其開源、小巧以及功能強大等優勢而備受青睞[4]。它可用于對服務器、網絡或對象模擬巨大的負載,在不同壓力類別下測試它們的強度及分析整體性能。JMeter支持對Web服務HTTP接口的性能壓測[5],但其在HTTP異步接口的性能壓測方面存在一定的局限性。JMeter對HTTP接口的壓測只能覆蓋到同步接口和異步接口的同步處理邏輯,無法覆蓋到異步接口內部的異步處理邏輯。單獨使用JMeter對HTTP異步接口進行的性能壓測不能覆蓋接口內部完整業務處理邏輯,因此JMeter的壓測結果不能反映出接口自身的真實性能情況。
本文根據HTTP異步接口內部業務實現特性,結合JMeter支持純Java腳本編寫的特點,設計了一套集JMeter工具、MySQL數據庫表設計[6]、模擬接口測試樁設計以及自定義Java腳本設計等為一體的性能測試方案。該方案能夠覆蓋HTTP異步接口完整業務處理邏輯,且通過在真實產品中進行性能壓測實踐,證明了該方案的可行性與實效性,彌補了JMeter在異步接口性能壓測中所表現出的不足。
性能測試方案的整體思路及具體實現按整個壓測過程可分為壓測前準備、JMeter壓測與數據收集以及結果統計分析三部分。
本性能測試方案所需測試環境主要涉及JMeter客戶機、被壓測接口所在服務器、模擬回調接口測試樁所在JBoss服務器、MySQL數據庫服務器。性能測試環境整體架構如圖2所示。

圖2 性能測試環境整體架構圖
壓測前準備主要完成MySQL數據庫服務搭建與數據庫表設計、模擬接口調用方的HTTP回調接口測試樁設計與實現及基于JBoss服務的部署、被壓測接口作特定處理,以及各服務器和JMeter所在客戶機環境性能調優。
搭建MySQL服務器,創建數據庫,設計數據表[7]。針對單級HTTP異步接口,即接口內部不調用其他異步接口,只需設計兩個數據表即可。一個為請求表,用于記錄被壓測HTTP接口收到的請求數據,一個為響應表,用于記錄被壓測接口異步響應數據。表字段設計分別見表1和表2。

表1 請求表

表2 響應表
針對二級HTTP異步接口,即接口內部又調用其他異步接口,需作擴展設計,即設計四個數據表。其中:三個請求表依次分別記錄被壓測HTTP接口收到的請求數據、被壓測接口內部調用其他異步接口時下發的HTTP請求數據、被壓測接口的回調接口收到的HTTP請求數據;一個響應表記錄被壓測接口的回調接口返回的異步響應數據。針對多級HTTP異步接口,可按上述邏輯繼續作擴展設計。
被壓測接口在接口內部增加兩部分特定業務處理。一是在請求處理開始之前將請求串插入MySQL庫請求表,二是將異步返回的響應數據按要求插入MySQL庫響應表。增加特定業務處理后的流程圖如圖3所示。

圖3 HTTP異步接口性能測試特有業務流程圖
搭建JBoss服務器,使用Java腳本基于Web Servlet技術[8]開發模擬請求方的HTTP回調接口的測試樁并打包成Web存檔文件部署在JBoss服務上。測試樁接口內部業務邏輯為接收被壓測接口異步返回的數據并按預定要求作出響應。為確保各服務器之間有良好的通信性能,需設定各測試用服務器在硬件與操作系統等配置方面與被壓測接口所在服務器保持一致,MySQL數據庫服務和JBoss服務在線程池、日志等級等方面作性能最優配置。整套測試環境在同一局域網內。
使用JMeter合理設計測試計劃,對HTTP異步接口進行壓測并在壓測過程中收集接口請求數據和異步返回的響應數據:1) 在JMeter測試計劃中,針對被壓測接口新建一線程組,在線程組中添加取樣器“HTTP請求”,并配置接口請求地址、請求方式及請求參數等數據。2) 使用JMeter配置元件“用戶定義的變量”定義請求串中可配且有可能需手動調整的參數,如數據庫配置信息等。使用JMeter配置元件“CSV Data Set Config”讀取需要從數據庫中提取的批量測試數據,在此之前需編寫自定義Java腳本實現從數據庫中提取批量數據并生成測試所需逗號分隔值(Comma-Separated Values,CSV)數據文件。3) 在JMeter前置處理器“BeanShell PreProcessor”中編寫Java腳本,調用事先用Java腳本編寫并打包好的自定義Jar包,實現對請求參數的特定處理,如對某請求參數數據加密或作簽名等。4) 使用JMeter斷言“響應斷言”判斷被壓測接口同步返回的響應數據是否正確。5) 使用JMeter監聽器“察看結果樹”檢查短時間高并發下異常信息,在長時間高并發下需禁用“察看結果樹”以確保JMeter自身性能良好。6) 使用JMeter監聽器“聚合報告”記錄并顯示壓測結果。
根據實際性能需求,在線程組的線程屬性和調度器配置中分別配置并發用戶數和壓測持續時間,啟動JMeter壓測。JMeter壓測過程中,將被壓測接口的請求數據和異步返回的響應數據分別插入MySQL數據庫請求表和響應表中。
對JMeter壓測結果以及壓測過程中收集的請求數據和響應數據作統計分析:1) 通過分析JMeter聚合報告結果,可評估異步接口中同步處理業務的性能。2) 采用自定義Java腳本對MySQL庫請求表和響應表中的數據作統計分析,評估HTTP異步接口內部完整業務的性能。
具體分析步驟:1) 比對請求表中記錄數和響應表中記錄數是否一致,若不一致,則說明有失敗的請求,若一致則繼續后續比對分析。2) 逐條讀取請求表中的記錄,根據業務流水號字段值到響應表中去查找對應記錄。若能找到,則繼續檢查響應數據是否正確,若正確則本次HTTP請求處理成功,若不正確則本次請求失敗。若根據業務流水號未能在響應表中查找到對應記錄,則本次HTTP請求失敗。3) 在逐條讀取請求表中記錄并作比對分析的過程中,統計記錄HTTP請求成功總數和失敗總數。若HTTP請求成功總數與請求表中記錄總數相等,則說明HTTP異步接口在高并發壓力下均能成功處理各HTTP請求。若不等,用請求失敗總數除以總請求數得到出錯率。4) 針對請求成功的記錄,根據響應表中記錄的業務處理時間與請求表中對應記錄的業務處理時間計算本次HTTP請求的處理耗時。統計所有成功的請求中的最大響應耗時、最小響應耗時和平均響應耗時。
某身份標識產品對外提供的短信服務(Short Messaging Service,SMS)簽名接口是一個復雜的二級異步調用接口,其向第三方服務提供的回調接口也是異步接口。SMS簽名接口及其回調接口相關的完整業務流程如圖4所示。

圖4 SMS簽名接口完整業務處理流程圖
SMS簽名業務完整處理邏輯分兩個階段,第一階段為從請求方向SMS簽名接口發送請求開始到SMS簽名接口向第三方服務下發短信下行(以下簡稱“MT”)請求為止,第二階段為從第三方服務向MO回調接口發送請求開始到短信上行(以下簡稱“MO”)回調接口向請求方發送異步處理結果為止。
根據性能測試方案中所述針對二級異步調用接口的數據庫表設計方法,在MySQL數據庫中新建四個表,分別為SMS簽名請求表、SMS簽名短信下行請求表、SMS簽名短信上行請求表、SMS簽名響應表。各請求表字段同表1,響應表字段同表2,四個表中的記錄通過業務流水號字段唯一關聯。SMS簽名請求表記錄SMS簽名接口的HTTP請求數據,SMS簽名短信下行請求表記錄SMS簽名接口內部下發的MT請求數據,SMS簽名短信上行請求表記錄MO回調接口的HTTP請求數據,SMS簽名響應表記錄MO回調接口內部下發的SMS簽名回調請求數據,即SMS簽名接口返回的異步響應數據。SMS簽名請求表和SMS簽名短信上行請求表可由被壓測接口進行數據插入,也可由請求發起方進行數據插入。由請求發起方進行數據插入,可將請求發起方與被壓測接口之間的網絡傳輸、Web服務等相關環境性能情況涵蓋在內,得出的性能評估結果也更全面,因此,本文采取由請求發起方進行數據插入的方式。被壓測的SMS簽名接口和MO回調接口內部分別增加特定處理邏輯,即SMS簽名接口中在下發MT消息前將即將下發的MT請求數據插入SMS簽名短信下行請求表,MO回調接口中在下發HTTP請求給請求方回調接口前將HTTP請求數據插入SMS簽名響應表。按請求方回調接口規則開發模擬測試樁供MO回調接口調用。
由于SMS簽名接口是二級異步調用接口,業務邏輯較復雜,因此,需要在前述性能測試方案基礎上做一定的延伸擴展。在同一個測試計劃的同一個線程組內創建兩個HTTP請求取樣器,分別對應SMS簽名接口和MO回調接口。SMS簽名接口取樣器內部的BeanShell前置處理器腳本中需增加將HTTP請求數據插入SMS簽名請求表。MO回調接口取樣器內部的BeanShell前置處理器腳本中需增加將HTTP請求數據插入SMS簽名短信上行請求表。編寫Java腳本用軟實現方式模擬終端內部處理邏輯生成簽名值并組裝成MO回調接口請求數據,以Jar包的形式供JMeter調用。基于MO回調接口內部有對MO消息與MT消息的數據關聯檢查,在MO回調接口前置處理器腳本中還需增加一層邏輯處理,即只有在SMS簽名短信下行請求表中查找到對應的記錄后才下發MO回調請求。根據產品實際性能需求,配置200個并發用戶數,循環100次,執行JMeter壓測。
采用性能測試方案中所述結果統計分析方法,對在壓測過程中插入MySQL數據庫四個表中的數據做擴展性統計分析,評估SMS簽名接口和MO回調接口內部完整業務邏輯性能情況。編寫自定義Java腳本,逐一提取SMS簽名請求表中記錄,在SMS簽名響應表中進行查找,檢查是否有對應的響應串并對響應串數據正確性作判斷。對于能找到對應響應串且響應串數據正確的記為請求成功,對于未找到或者找到但相應數據不正確者記為請求失敗,記錄請求成功總數和失敗總數。對于請求成功的記錄,根據SMS簽名請求表和SMS簽名短信下行請求表中的業務處理時間字段數據,按前述統計方式統計第一階段SMS簽名接口內部完整業務邏輯處理平均耗時,根據SMS簽名短信上行請求表和SMS簽名響應表中的業務處理時間字段數據,統計第二階段MO回調接口內部完整業務邏輯處理平均耗時,記錄第一階段耗時、第二階段耗時以及兩個階段的總耗時,統計分析所有請求成功的記錄的平均響應耗時、最大響應耗時和最小響應耗時。對于請求失敗的記錄,記錄相應的業務流水號,便于作后續的問題排查分析。以上統計所得數據全部記入文件備查。
壓測生成的JMeter聚合報告顯示:SMS簽名接口總請求數為20 000,內部同步處理邏輯平均響應耗時為297毫秒,最小響應耗時為48毫秒,出錯率為0.00%;MO回調接口總請求數為20 000,內部同步處理邏輯平均響應耗時為1 267毫秒,最小響應耗時為90毫秒,出錯率為0.00%。兩個接口內部同步處理邏輯性能尚在可接受范圍內。
對JMeter壓測過程中插入數據庫表中的各請求數據和響應數據作統計分析。JMeter發給SMS簽名接口的總請求數為20 000,發給MO回調接口的總請求數為20 000。異步收到結果的總記錄數為20 000,且所有記錄的響應數據均正確。其中,能與請求相關聯的有19 896條記錄,無法關聯的有104條。能與請求相關聯的所有記錄中,最小響應耗時50 394毫秒,最大響應耗時56 522毫秒,平均響應耗時51 270毫秒。
對結果作進一步分析,從發給MO回調接口的總請求數以及接口對應的后臺日志可以確認,MO回調接口的20 000次請求中有104次未能成功返回異步結果,錯誤率為0.52%。通過比對JMeter發出請求的時間與接口對應后臺日志中顯示的收到HTTP請求的時間,發現服務端接口收到請求的時間比JMeter發出請求的時間滯后約25秒。統計分析生成的部分結果示例如圖5所示。

圖5 統計分析生成的部分結果示例
綜上,基于本文提出的性能測試方案,不僅使用JMeter完成了對SMS簽名異步接口和MO回調異步接口內部的同步業務邏輯的性能評測,還根據壓測過程中收集的數據及對數據的統計分析完成了對兩個異步接口內完整業務邏輯的性能評測,發現了僅僅使用JMeter壓測無法檢出的兩個性能問題。實踐證明,本文所描述的性能測試方案切實可行且有明顯實效。
本文結合異步接口內部處理邏輯,從分層壓測和統計分析的角度出發,整合JMeter性能測試計劃設計、MySQL數據庫表設計、模擬接口測試樁設計和自定義Java腳本設計等多方面的技術,設計了一套能夠覆蓋HTTP異步接口內部完整處理邏輯的性能測試方案。通過在真實產品中進行性能壓測實踐,證明了該方案在HTTP異步接口性能評測方面的可行性與實效性。基于分層壓測和統計分析的特性,該方案具有良好的可擴展性,不僅適用于具有二級異步調用關系的接口性能評測,也可以通過延伸擴展應用于具有多級異步調用關系的復雜接口性能評測。