Jmeter使用Websocket外掛測試SingalR,外加還有阿里雲PTS的Jmeter原生測試爬坑日誌。
題外話:距離我的上一篇部落格已經過去7年多了,我實在是個不務正業的程式設計師,遇到測試方面的東西總想分享一下,因為可用的資料實在太少了(包括國外的資料)。
本人不喜歡授人以魚,所以不會直接給出問題和解決方案的鍵值對,各位看官多多包涵。
先說說這次的場景:
在開發中我們使用.Net Core的SignalR(底層實現為包括WebSocket的多個協議的封裝)作為長連線方案。同時對於該長連線的壓力測試也是一個非常重要的環節。
坑1:Jmeter連線SingalR
我通過Chrome檢視時,看到有一個連線是連到/HubName?id=XXXXXXXXXXXX,所以我果sha斷bi的直接用了這個連線。一直提示404。此時覺得應該是我的外掛或者Jmeter本身又或者是我老婆不讓我連線這個介面。多方嘗試無果,坐飛機去曾經的人類曙光查。(7年後我還是想吐槽一下百度你真的是給我們提供了一個測試Internet連線的好工具)
查到這個: 這個是病毒不要點點了地球會爆炸!
巨硬的官方文件,重點畫出來,自己看大圖
這個是SignalR用來建立連線的請求,跑回Chrome一看果然有這個請求,這個請求成功後會帶一個ConnectID,後面的連線可以使用這個ID做引數來連線。嗯,原來是少了這一步。少年且慢,是不是拿著葵花寶典就想著去自宮了?再繼續往下看:
是的,這裡寫著,若不自宮亦能成功。
原來直接去對/HubName不帶queryString進行連線也可以建立連線。
至於為什麼之前帶引數會提示404(或者409)。上面那張圖自己找去
至此,連線問題解決!手動撒花~
坑2:阿里雲PTS,Jmeter原生模式執行Websocket提示“啟動錯誤”
本來準備弄個壓測伺服器對等的壓測。某天中午睡覺夢到蛇咬自己尾巴,然後就得出了苯的分子式的這個人並不是我。不過我確實午睡的時候突然想到有沒有更便宜的方案?一查果然有云壓測。在根本就沒有經過分析對比的情況下我選擇了阿里雲PTS並且讓老闆給我掏了158大洋買了個雲玩具。
很方便的是它可以上傳jar外掛和引數化csv檔案,這點基本解決了壓測的絕大部分問題。
在自信滿滿的寫好了WebSocket指令碼並且上傳好外掛之後,執行起來Duang(看我嘴型),啟動錯誤,並且沒有任何什麼卵提示。提交工單吧:
然後客服GG告訴我他本地開啟檔案確實也Duang了,說我指令碼檔案是不是有問題。(這裡注意以下他睪貴的標題欄,並不是瘟到死,我手上沒有Mac無法確認是否是跨平臺的問題)
[手動黑人問號],繼續追問下,GG很熱心的幫我找到了錯誤的位置。
[手動懵逼臉1秒露出淫笑],讓我想起來好像Chrome除錯下,在每個WebSocket內請求的結尾都會顯示一個方框。並且這個方框被複制到了測試指令碼中。刪掉這個方框後,請求就會超時,這讓我更加確認了這是一個結束符,查閱Unicode以後更加肯定了
並且我注意到(忘了哪裡找到的小道訊息),1e在XML中是一個非法字元,而jmx就是xml格式。
那麼我不放在指令碼內部不就完了?找到指令碼,勾選從傳送檔案內容,把包括請求內容和結束符都放到一個txt中,選擇該檔案。
成功啟動!撒花!
坑3:接上個坑的解決方案之後
其實有一些經驗的人應該注意到一個可能存在的問題:如果請求內容也放到txt中那麼就無法引數化了。簡單測試以後問題確認。
那麼現在就在石頭和硬的東西中間(Between a rock and a hard place),要麼不能引數化,要麼老闆給我買的玩具報廢。依照馬克思恩格斯以及毛爺爺思想鄧爺爺理論中最重要的廢物利用原則,我還是想想辦法吧。
Websocket的資料收發,其實和socket的資料收發形式是很像的。底層都是以位元組流的方式。這也是為什麼每條訊息需要一個結束符來表示訊息的末尾,否則服務端無法確認資料包的結束。等不到結束符SignalR也不會認為收到了訊息,兩邊會一直等到超時為止。
既然和Socket很像,那麼就有可能有粘包問題(不懂自己百度吧,我也不懂)我猜想,這裡可否利用一下粘包的特性?
解決方案如下:
連線成功後,
1、建立一個WebSocket Writer,把請求內容直接寫到指令碼檔案中,這裡不傳送結束符,同時不等待響應。那麼這裡的內容就可以引數化了
2、再建立一個WebSocket request-respone, 此時用上面檔案的方式僅僅傳送一個結束符,然後接收響應。
相當於把兩個請求合成了一個請求,(request1&request2)-response
方案得逞,撒