性能測試 - Locust WebSocket client

Max.Bai

2024.10

0. 背景

Locust 是性能測試工具,但是默認只支持http協議,就是默認只有http的client,需要其他協議的測試必須自己擴展對于的client,比如下面的WebSocket client。

1. WebSocket test Client
“”“
Max.Bai
Websocket Client
”“”
import json
import logging
import secrets
import threading
import time
from typing import Callable, Optionalimport websocket
from locust import eventslogger = logging.getLogger(__name__)class WebSocketClient:def __init__(self, host: str, log_messages: bool = False):self._host: str = hostself._id: str = secrets.token_hex(8)self._alias: Optional[str] = Noneself._ws: Optional[websocket.WebSocketApp] = Noneself.log_messages = log_messagesself.count_recv_type = Falseself.heartbeat_auto_respond = Falseself._recv_messages: list = []self.messages: list = []self._sent_messages: list = []def __enter__(self):self.connect()return selfdef __exit__(self, type, value, traceback):self.disconnect()@propertydef tag(self) -> str:tag = f"{self._host} <{self._id}>"if self._alias:tag += f"({self._alias})"return tagdef connect(self, alias: Optional[str] = None, headers: Optional[dict] = None, on_message: Optional[Callable] = None):if not self._ws:self._alias = aliasself._ws = websocket.WebSocketApp(url=self._host,header=headers,on_open=self._on_open,on_message=on_message if on_message else self._on_message,on_close=self._on_close,)thread = threading.Thread(target=self._ws.run_forever)thread.daemon = Truethread.start()time.sleep(3)else:logger.warning("An active WebSocket connection is already established.")def is_connected(self) -> bool:return self._ws is not Nonedef disconnect(self):if self._ws:self._ws.close()self._alias = Noneelse:logger.warning("No active WebSocket connection established.")def _on_open(self, ws):logger.debug(f"[WebSocket] {self.tag} connected.")events.request.fire(request_type="ws_client",name="connect",response_time=0,response_length=0,)def _on_message(self, ws, message):recv_time = time.time()recv_time_ms = int(recv_time * 1000)recv_time_ns = int(recv_time * 1000000)logger.debug(f"[WebSocket] {self.tag} message received: {message}")if self.log_messages:self._recv_messages.append(message)self.messages.append(message)# public/respond-heartbeatif self.heartbeat_auto_respond:if "public/heartbeat" in message:self.send(message.replace("public/heartbeat", "public/respond-heartbeat"))if self.count_recv_type:try:msg = json.loads(message)id = str(msg.get("id", 0))if len(id) == 13:resp_time = recv_time_ms - int(id)elif len(id) == 16:resp_time = (recv_time_ns - int(id)) / 1000elif len(id) > 13:resp_time = recv_time_ms - int(id[:13])else:resp_time = 0method = msg.get("method", "unknown")code = msg.get("code", "unknown")error = msg.get("message", "unknown")# send_time = int(msg.get("nonce", 0))if method in ["public/heartbeat", "private/set-cancel-on-disconnect"]:events.request.fire(request_type="ws_client",name=f"recv {method}",response_time=0,response_length=len(msg),)elif code == 0:events.request.fire(request_type="ws_client",name=f"recv {method} {code}",# response_time=recv_time - send_time,response_time=resp_time,response_length=len(msg),)else:events.request.fire(request_type="ws_client",name=f"recv {method} {code}",response_time=resp_time,response_length=len(msg),exception=error,)except Exception as e:events.request.fire(request_type="ws_client",name="recv error",response_time=0,response_length=len(msg),exception=str(e),)def _on_close(self, ws, close_status_code, close_msg):logger.debug(f"[WebSocket] {self.tag} closed.")self._ws = Noneevents.request.fire(request_type="ws_client",name="close",response_time=0,response_length=0,)def set_on_message(self, on_message: Callable):self._ws.on_message = on_messagedef send(self, message: str):if self._ws:self._ws.send(data=message)if self.log_messages:self._sent_messages.append(message)logger.debug(f"[WebSocket] {self.tag} message sent: {message}")else:logger.warning(f"No active [WebSocket] {self.tag} connection established.")raise ConnectionError("No active [WebSocket] connection established.")def clear(self):self._recv_messages = []self._sent_messages = []self.messages = []def expect_messages(self,matcher: Callable[..., bool],count: int = 1,timeout: int = 10,interval: int = 1,) -> list:"""Expect to receive one or more filtered messages.Args:matcher (Callable): A matcher function used to filter the received messages.count (int, optional): Number of messages to be expected before timeout. Defaults to 1.timeout (int, optional): Timeout in seconds. Defaults to 10.interval (int, optional): Interval in seconds. Defaults to 1.Returns:list: A list of messages filtered by the matcher."""deadline: float = time.time() + timeoutresult: list = []  # messages filtered by the matcherseen: list = []  # messages already seen by the matcher to be excluded from further matchingwhile time.time() < deadline:snapshot: list = [*self._recv_messages]for element in seen:if element in snapshot:snapshot.remove(element)result.extend(filter(matcher, snapshot))if len(result) >= count:breakseen.extend(snapshot)time.sleep(interval)if len(result) < count:logger.warning(f"({self.tag}) Expected to receive {count} messages, but received only {len(result)} messages.")return result
2. 如何使用
class PrivateWsUser(User):def on_start(self):self.ws_client=WebSocketClient("wss://abc.pp.com/chat", log_message=True)self.ws_client.connect()@taskdef send_hello()self.ws_client.send("hello world")
3. 擴展

可自行擴展on_message 方法,上面的on_message 方法是json 格式的信息處理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66317.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66317.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66317.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【藍橋杯選拔賽真題63】C++奇數 第十四屆藍橋杯青少年創意編程大賽 算法思維 C++編程選拔賽真題解

目錄 C++奇數 一、題目要求 1、編程實現 2、輸入輸出 二、算法分析 三、程序編寫 四、運行結果 五、考點分析 七、推薦資料 C++奇數 第十四屆藍橋杯青少年創意編程大賽C++選拔賽真題 一、題目要求 1、編程實現 給定兩個正整數N和M(10≤N<M≤10000),請找出N到M…

KubeSphere 與 Pig 微服務平臺的整合與優化:全流程容器化部署實踐

一、前言 近年來,為了滿足越來越復雜的業務需求,我們從傳統單體架構系統升級為微服務架構,就是把一個大型應用程序分割成可以獨立部署的小型服務,每個服務之間都是松耦合的,通過 RPC 或者是 Rest 協議來進行通信,可以按照業務領域來劃分成獨立的單元。但是微服務系統相對…

(學習總結20)C++11 可變參數模版、lambda表達式、包裝器與部分新內容添加

C11 可變參數模版、lambda表達式、包裝器與部分新內容添加 一、可變參數模版基本語法及原理包擴展emplace系列接口 二、lambda表達式lambda表達式語法捕捉列表lambda的原理lambda的應用 三、包裝器bindfunction 四、部分新內容添加新的類功能1.默認的移動構造和移動賦值2.聲明時…

Linux的常用命令(一)

目錄 一、文件處理命令 1.文件處理命令ls 2.文件處理命令cd 3.文件處理命令pwd 4.文件處理命令touch 5.文件處理命令mkdir 6.文件處理命令cp 7.文件處理命令mv 8.文件處理命令rm 9.文件處理命令cat 10.文件處理命令more 11.文件處理命令head 12.文件處理命令tail …

東芝e-STUDIO2829A復印機提示“維護”該如何操作

東芝e-STUDIO2829A復印機基本參數: 產品類型 數碼復合機 顏色類型 黑白 涵蓋功能 復印/打印/掃描 最大原稿尺寸 A3 處 理 器 500MHz 內存容量 標配:512MB,選配:1GB 供紙容量 標配紙盒:350頁(A4),最大容…

春秋杯-WEB

SSTI 可以看到主頁那里有個登錄測試之后為ssti {{4*4}} fenjing梭哈即可得到payload {{((g.pop.__globals__.__builtins__.__import__(os)).popen(cat flag)).read()}}file_copy 看到題目名字為file_copy&#xff0c; 當輸入路徑時會返回目標文件的大小&#xff0c; 通…

警惕IDEA 2024版重大Bug問題:LomBok失效、Gradle沖突、Spring Boot啟動錯誤

一直以來我認為工具類的軟件是越新越好&#xff0c;因為工具代表著一定的先進性&#xff1b;但是IDEA 2024好好的給我上了一課&#xff0c;比如lombok 不起作用、比如Spring Boot 3.4.x 啟動報錯、再比如MyBatis log plus沖突、再比如Gradle插件沖突. 一、Lombok 失效問題 請不…

《深度學習神經網絡訓練:數據集下載資源列表》

深度學習神經網絡訓練&#xff1a;數據集下載資源列表 一、數據集下載的重要性 在當今數字化時代&#xff0c;數據集下載對于各個領域的研究與發展都具有不可忽視的重要意義。尤其在機器學習、深度學習以及各類數據驅動的科研項目中&#xff0c;數據集更是起到了基礎性的支撐…

GPT-5 傳言:一場正在幕后發生的 AI 變革

新的一年&#xff0c;讓我們從一個引人入勝的話題開始&#xff1a;如果我告訴你&#xff0c;GPT-5 并非虛構&#xff0c;而是真實存在呢&#xff1f;它不僅真實存在&#xff0c;而且正在你看不見的地方悄然塑造著世界。我的基本假設是&#xff1a;OpenAI 已經秘密開發出 GPT-5&…

【Unity3D】利用Hinge Joint 2D組件制作繩索效果

目錄 一、動態繩索 &#xff08;可移動根節點&#xff09; 二、靜態繩索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事項 一、動態繩索 &#xff08;可移動根節點&#xff09; 動態繩索 DynamicRope空物體 Anchor和whitecircle是相同位置的物體&#xff…

【12】Word:張老師學術論文?

目錄 題目 ?NO2 NO3 NO4 NO5 NO6 NO7.8 題目 NO2 布局→頁面設置→紙張&#xff1a;A4→頁邊距&#xff1a;上下左右邊距→文檔網格&#xff1a;只指定行網格→版式&#xff1a;頁眉和頁腳&#xff1a;頁腳距邊界&#xff1a;1.4cm居中設置論文頁碼&#xff1a;插入…

OpenCV相機標定與3D重建(56)估計物體姿態(即旋轉和平移)的函數solvePnPRansac()的使用

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 使用RANSAC方案從3D-2D點對應關系中找到物體的姿態。 cv::solvePnPRansac 是 OpenCV 中用于估計物體姿態&#xff08;即旋轉和平移&#xff09;的…

怎么用python寫個喚醒睡眠電腦的腳本?

環境&#xff1a; win10 python3.12 問題描述&#xff1a; 怎么用python寫個喚醒睡眠電腦的腳本&#xff1f; 解決方案&#xff1a; 1.喚醒處于睡眠狀態的電腦通常不是通過編程直接實現的&#xff0c;而是依賴于硬件和操作系統提供的特性。對于Windows系統&#xff0c;可…

基于 HTML5 Canvas 制作一個精美的 2048 小游戲--day 1

基于 HTML5 Canvas 制作一個精美的 2048 小游戲 在這個快節奏的生活中&#xff0c;簡單而富有挑戰性的游戲總能給我們帶來樂趣。2048 是一款受歡迎的益智游戲&#xff0c;不僅考驗智力&#xff0c;還能讓人回味無窮。今天&#xff0c;我帶領大家將一起學習如何使用 HTML5 Canv…

每日進步一點點(網安)

今日練習題目是PHP反序列化&#xff0c;也學習一下說明是序列化和反序列化 1.PHP序列化 序列化是指將數據結構或對象轉換為可傳輸或可儲存的格式的過程。這通常需要將數據轉換為字節流或者其他編碼格式&#xff0c;以便在不同系統和應用程序之間進行傳輸或存儲 在PHP中&…

MySQL數據庫入門到大蛇尚硅谷宋紅康老師筆記 基礎篇 part 5

第05章_排序與分頁 排序 #第05章_排序與分頁#1. 排序# 如果沒有使用排序操作&#xff0c;默認情況下查詢返回的數據是按照添加數據的順序顯示的。 SELECT * FROM employees;# 1.1 基本使用 # 使用 ORDER BY 對查詢到的數據進行排序操作。 # 升序&#xff1a;ASC (ascend) # 降…

【專題一 遞歸】21. 合并兩個有序鏈表

1.題目解析 2.講解算法原理 解法:遞歸-> 重復的子問題 重復子問題 ->函數頭的設計 合并兩個有序鏈表--->Node dfs(l1&#xff0c;l2) 只關心某一個子問題在做什么事情 ->函數體的設計 比大小l1→next dfs( l1.next, l2)return l1 遞歸的出口 if(l1null)return l2…

OpenCV基礎:獲取子矩陣的幾種方式

目錄 相關閱讀 方法一&#xff1a;使用切片操作 方法二&#xff1a;使用高級索引 方法三&#xff1a;使用條件篩選 方法四&#xff1a;使用 numpy 的 take 函數 相關閱讀 OpenCV基礎&#xff1a;矩陣的創建、檢索與賦值-CSDN博客 OpenCV基礎&#xff1a;圖像運算-CSDN博客…

Java語言的數據結構

Java 提供了多種內置的數據結構&#xff0c;這些數據結構可以分為兩大類&#xff1a;基本的數組&#xff08;Array&#xff09;和集合框架&#xff08;Collections Framework&#xff09;。集合框架又細分為多個接口和實現類&#xff0c;提供了豐富的功能來管理對象集合。以下是…

Visual Studio Community 2022(VS2022)安裝方法

廢話不多說直接上圖&#xff1a; 直接上步驟&#xff1a; 1&#xff0c;首先可以下載安裝一個Visual Studio安裝器&#xff0c;叫做Visual Studio installer。這個安裝文件很小&#xff0c;很快就安裝完成了。 2&#xff0c;打開Visual Studio installer 小軟件 3&#xff0c…