JMeter測試WebSocket的經驗總結
最近有一個微信聊天系統的專案需要效能測試,既然是測試微信聊天,肯定繞不開websocket介面的測試,首選工具是Jmeter,網上能搜到現成的方法,但是網上提供的jar包往往不是最新的,既然是用最新版本的Jmeter4.0,那麼所依賴的外掛jar包也應該追求新的。所以提供了以下連結供大家下載(甚至連原始碼都提供):
(1)Jmeter工具
(2)websocket請求模板 JMeterWebSocketSamplers
(3)jetty-http
(4)jetty-io
(5)jetty-util
(6)
將(2)~(4)中下載的jar包放到Jmeter以下目錄下,就能夠被呼叫了:
#將你下載的所有jar包,複製到
apache-jmeter-4.0\lib\ext
#該目錄下
一、啟動JMeter
windows環境開啟 bin下的jmeter.bat
linux環境開啟bin下的jmeter.sh
由於Jmeter4.0的介面是深色的(看不清字型),預設語言是英語,我們可以調一下。先修改語言:在bin\jmeter.properties中找到#language=en,將前面的註釋【#】去掉,改為language=zh_CN。這樣啟動後就是中文版的,然後到選項-->外觀中選擇Metal,這就變成傳統Jmeter樣式。
二、新增websocket Sampler
先在測試計劃中新增執行緒組,然後右鍵添Sampler時就能看到websocket的模板:
常用的就是websocket request-response Sampler(連線+傳送data或者只發data),其次是WebSocket Open Connection(只連線,不傳送data)
配置舉例如下:
說明:(1)Connection:有兩項,第一項是使用已有連線,就是上一個websocket請求所建立的連線通道,選擇後Server URL全置灰只讀不可操作。第二項是新建連線通道。
(2)Server URL:可以傳送ws協議和wss協議(加密的websocket),以上圖的配置所對應的連線串如下:
ws://192.18.24.211:8888/testPath (這一點比舊版本的websocket外掛配置要清晰明瞭)
(3)Data:支援文字(包括JSON)和Binary二進位制資料的傳送。預設請求響應的超時時間為6S,超過這個時間報錯。(對於Data的文字格式最好是自己抓包獲取,比如谷歌瀏覽器的F12開發者工具或Fiddler,不要太相信開發提供的介面文件)。
三、使用小技巧
1、Path和Requst data要注意編碼格式
websocket傳送資料到後端,與http請求的原理是相通的,所以傳送的資料如果含有非常字元,如"/"、"+"、"%"、引號等,就會引起解析錯誤,所以需要特別注意,比如:
如上所示,websocket請求的上一個請求TR-token可以獲取一個token串(通過正則表示式提取器提取),而這個串的格式可能是這樣的:Ivj6eZRx40+MTx2Zv/G8nA,可以發現含有"+"、"/"字元,而我們需要把這個串作為Path的一部分來發送,那麼我們就需要對${token}變數進行URL轉碼,用到jmeter的函式 __urlencode()
2、可以通過邏輯控制器來模擬群發訊息
(1)通過迴圈控制器調取引數化檔案(CSV)裡的使用者資訊表來實現群發訊息,如下所示:
(2)或者先通過傳送請求來獲取使用者資訊(正則表示式提取),再用ForEach調取使用者組變數傳送訊息,如下所示:
3、以時間戳來檢視當前聊天記錄應注意websocket的response延時
在併發的情況下,websocket請求延時可能要遠大於http請求,比如延時2秒以上(從傳送訊息到看到聊天面板已經過了2秒以上)。所以在jmeter中用時間戳函式${__time(,)}來表示最新一條聊天記錄的時間是不可靠的。我們應該在websocket請求中插入正則表示式提取器,通過在response中獲取其時間才能確保訊息接收時間準確(即不要用客戶端時間來判斷你的聊天時間)。
(1)先提取websocket反饋的服務端時間戳
(2)再作為查詢當前聊天記錄的時間戳依據
4、最後說一下jmeter4.0,如果是要做分散式測試,jmeter4.0預設是要求RMI傳輸必須SSL加密的,否則jmeter-server就啟動不了,我們可以用簡單的配置來回避這個問題。就是server端和client端的jmeter我們統一做如下配置:
(1)用編輯器開啟bin/user.properties檔案
(2)找到server.rmi.ssl.disable,將#註釋符去掉,改成 server.rmi.ssl.disable=true
現在可以奔跑了,我直接用以下shell指令碼實現在linux下分散式呼叫jmeter-server進行測試,並生成html報告:
#!/bin/bash
testAPI="websocket-test.jmx" #jmeter測試指令碼
Cur_Dir=$(cd "$(dirname "$0")"; pwd)
sed -i "s/csvData\\\/csvData\//g" $Cur_Dir/jmeter4.0/bin/${testAPI} #替換引數路徑斜槓\為/
$Cur_Dir/jmeter4.0/bin/jmeter -n -t $Cur_Dir/jmeter4.0/bin/${testAPI} -R 172.16.1.67,172.16.5.241 -l $Cur_Dir/DashReport/log-$(date -d "today" +"%Y%m%d%H%M%S").csv -e -o $Cur_Dir/DashReport/htmlReport-$(date -d "today" +"%m%d%H%M%S")
另外測試還開啟了jmeter監控工具(influxDB+grafana),具體安裝配置方式參見我的另一篇文章《關於Jmeter長時間壓測的視覺化監控報告》(區別是這篇文章用的是windows版的,而我這次測試用的是Linux版的,網上有相關下載,開源工具)。
新增配置後,監控後的效果如下:
補充:除了常用的WebSocket Open Connection和WebSocket request-response 這兩個Sampler,WebSocket Single Read Sampler也比較常用,一般是用在群聊訊息已讀回執的傳送。比如在微信群裡發一條訊息,通過抓包分析,可以看到客戶端是發出了兩條訊息(同時服務端也回發了兩條訊息),如下所示:
第二條訊息表示傳送訊息已讀回執,按以往的方式,我們需要通過正則表示式提取器提取第一條訊息的返回值,然後傳送第二條訊息,這樣的效率就不高,我們可以直接用WebSocket Single Read Sampler來模擬訊息的已讀回執:
為了避免這條已讀回執訊息偶爾出現超時報錯,我們可以將Optional read勾選。