jmeter測試基於SignalR的Websocket過程中的一些總結


引言

ASP.NET Core SignalR 作為微軟官方出品的一個實時Web中間件功能庫,可以使服務器端代碼可以將內容立即推送到客戶端。

SignalR supports the following techniques for handling real-time communication (in order of graceful fallback):

SignalR automatically chooses the best transport method that is within the capabilities of the server and client.

背景

​ 在使用jmeter對自己搭建的聊天服務(消息轉發服務)進行壓力測試的時候,發現和傳統的websocket連接測試過程不同,比如websocket連接地址是什么,端口是什么,這些都不是signalr去暴露出來的,因此進入了深一步的研究。

​ 通俗來講,SignalR只是一個實時Web的中間件,它支持的通訊模式有WebSockets\SSE\Long Polling ,目前我們只考慮最優的websocket模式,那么它的websocket地址是什么呢?

​ 因為我是將SignalR中間件寄宿於Web MVC中,然后部署在Linux下,所以這里websocket的地址就是 127.0.0.1/chatHub ,后面的名稱,具體的路由地址,看你再starup.cs中如何映射SignalR請求地址和后台中的Hub名稱。

過程分析

通過web端監控,發現連接客戶端連接SignalR會執行兩個步驟

negotiate

返回的結果,注意看下這個connectionToken ,這個token會作為 一個參數在接下來的chatHub中去請求服務器。

{
  "negotiateVersion": 1,
  "connectionId": "eZuczhINi9cewADWJO4kXA",
  "connectionToken": "SZyT2pHeOXXNaCrveIJx5A",
  "availableTransports": [
    {
      "transport": "WebSockets",
      "transferFormats": [
        "Text",
        "Binary"
      ]
    },
    {
      "transport": "ServerSentEvents",
      "transferFormats": [
        "Text"
      ]
    },
    {
      "transport": "LongPolling",
      "transferFormats": [
        "Text",
        "Binary"
      ]
    }
  ]
}

源碼文檔的描述中可以看出,如果在請求的時候,沒有發送negotiateVersion這個參數,它會默認為0,且此時返回的數據中是沒有connectionToken這個參數的。

並且在連接websocket的時候,如果對id這個參數賦值的話,如果它是錯誤的,會提示你無法連接,但是如果你不傳這個id,它其實是可以連接上的。

連接websocket-->chatHub

WebSockets傳輸是唯一的,因為它是全雙工的,並且可以在單個操作中建立持久連接。結果,不需要客戶端使用該POST [endpoint-base]/negotiate請求來預先建立連接。它還在其自己的幀元數據中包含所有必需的元數據。

通過建立與WebSocket的連接來激活WebSocket傳輸[endpoint-base]。該可選的 id查詢字符串值被用來識別附加到連接。如果沒有id查詢字符串值,則建立新連接。如果指定了參數,但沒有與指定ID值的連接,404 Not Found則返回響應。收到此請求后,將建立連接,並且服務器將101 Switching Protocols立即通過WebSocket升級()進行響應,以准備發送/接收幀。WebSocket OpCode字段用於指示幀的類型(文本或二進制)。

如果已經存在與端點連接關聯的WebSocket連接,則不允許建立第二個WebSocket連接,並且將失敗,並顯示409 Conflict狀態代碼。

建立連接時的錯誤通過返回500 Server Error狀態碼作為對升級請求的響應來處理。這包括初始化EndPoint類型的錯誤。未處理的應用程序錯誤會觸發WebSocketClose框架,其原因碼與規范中的錯誤相匹配(對於錯誤消息(例如消息過大或無效的UTF-8))。對於連接過程中的其他意外錯誤,將使用非1000 Normal Closure狀態代碼。

jmeter配置

1.negotitate請求

2.打開websocket連接

3.發送webscoket數據

在SignalR中,總是要從客戶端發送的第一幀是HandshakeRequest {“ protocol”:“ json”,“ version”:1}

4.添加websocket心跳機制

SignalR的心跳機制是底層自動發送的,而且客戶端和服務端並不會構成實時響應,就類似於,服務端和客戶端兩者分別自己發送心跳,我們模擬一個客戶端的發送心跳

這個使用jmeter的Sampler-->websocket Single Write Sampler 添加即可,保持與websocket連接,發送內容為 {"type":6}

5.其他

  • 基於SignalR的websocket在模擬測試發送消息的時候,都需要在后面添加一個特殊符號,我們可以從web頁面F12中【NetWork】里抓取這個特殊符號。
  • jmeter中的websocket組件似乎針對廣播模式的場景支持不太友好,因為廣播模式下,客戶端不知道什么時候會收到服務端的消息,或者說會一直收到服務端的消息(並發人數夠多的時候),而如果此時沒有讀取websocket中的(通道中)的消息,可能會造成網路堵塞,然后測試用例就開始出現異常,從而出現連接斷開

不使用 SignalR 的 WebSocket

微軟官方也提供了不使用 SignalR 的 WebSocket的方法,有興趣的小伙伴可以研究下:

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets?view=aspnetcore-5.0

其他參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM