JMeter-SSE響應數據自動化

結構圖

在這里插入圖片描述

背景:

需要寫一個JMeter腳本來進行自動化測試,主要是通過接口調用一些東西,同時要對響應的數據進行處理,包括不限于錯誤信息的輸出。

1.SSE(摘錄)

SSE(Server-Sent Events)是一種基于HTTP協議、允許服務器主動向客戶端推送實時更新的技術?。它特別適用于單向數據流的實時場景,例如消息通知、AI對話流式響應等,通過保持長連接實現持續數據傳輸。

2.實現思路

2.1 用戶自定義變量組件

主要是用來統一更換和維護環境變量的,比如線上、線下環境host的切換

2.2 HTTP信息頭管理

設置https請求的信息頭,比如token,數據格式等等
在這里插入圖片描述

2.3 CSV 數據文件設置

參數如下圖設置
在這里插入圖片描述
變量名稱:appId,query,appName,needFiles,file

對應vars中的變量,變量值是根據分隔帶JMeter自動處理的,變量名稱 數量和分隔后的變量值 數量不對應也沒影響,兩者缺少的值會忽略或者設置為空值

2.4 HTTP請求組件

需要設置消息體數據,請求url等
在這里插入圖片描述
下面三個插件,歸類到HTTP請求的子目錄下:如圖
在這里插入圖片描述

2.4.1 JSR223 預處理程序

主要來處理一下請求中消息體數據中的一個參數,fileParam

根據csv文件中的標記來確定fileParam的具體值,如下代碼

import org.json.JSONObject;
import org.json.JSONArray;
import java.util.ArrayList;//判斷是否需要 files 參數
private Boolean needFiles(String str) {if("1".equals(str)) {return true;}else {return false;}
}//設置 files 參數
private void setFiles(String fileParams) {try{//將fileParams轉為json格式JSONObject jsonResponse = new JSONObject(fileParams);// 提取各個參數String filename = jsonResponse.optString("xxx", "");String fileHash = jsonResponse.optString("xxx", "");Integer filesize = jsonResponse.optInt("xxx", 0);  // Integer類型String extension = jsonResponse.optString("xxx", "");String mimeType = jsonResponse.optString("xxx", "");// 創建 JSON 對象數組(List<Map> 格式)JSONArray fileParamsArray = new JSONArray();JSONObject fileObj = new JSONObject();fileObj.put("xxx", xxx);fileObj.put("xxx", xxx);fileObj.put("xxx", xxx);fileObj.put("xxx", xxx);fileObj.put("xxx", xxx);fileParamsArray.put(fileObj);// 存入 vars(JSON 字符串)vars.put("fileParam", fileParamsArray.toString());} catch (Exception e) {log.error("設置 files 參數 失敗!", e);prev.setSuccessful(false);}	}    try {String str = vars.get("needFiles");	String fileParams = vars.get("file");if(needFiles(str)){//需要文件參數setFiles(fileParams);}else{//不需要文件參數,設置為空JSONArray fileParamsArray = new JSONArray();vars.put("fileParam",fileParamsArray.toString());	}
} catch (Exception e) {log.error("判斷是否需要文件參數 失敗!", e);prev.setSuccessful(false);
}
2.4.2 JSR223 后置處理程序

對SSE響應的數據進行處理和判斷,確定好哪個數據是一次請求結束的標記

下面代碼是根據 event 含有 message_end 字段來做執行成功的標記
error字段來錯失敗的標記,同時進入斷言

下面的代碼是逐行匹配、逐個處理 SSE 事件適合實時響應場景

import org.apache.jmeter.samplers.SampleResult;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.json.JSONObject;
import org.json.JSONException;// 判斷是否是流式響應
private Boolean isStreamingResponse(String response) {return response.contains("data: {");
}// 非流式響應處理
private void handleNonStreamingResponse(String response, SampleResult prev) throws Exception {JSONObject jsonResponse = new JSONObject(response);String msg = jsonResponse.get("msg");if ("智能體不存在".equals(msg)) {vars.put("response_type", "智能體不存在");vars.put("error_msg", msg);vars.put("isExist", "false");} else {vars.put("response_type", "非流式響應,未知錯誤");vars.put("error_msg", msg);vars.put("isExist", "false");}
}// 流式響應處理
private void handleStreamingResponse(String response, SampleResult prev) throws Exception {vars.put("response_type", "streaming");// 正則表達式,確保匹配完整JSONPattern pattern = Pattern.compile("data:\\s*(\\{[^{}]*\\})", Pattern.DOTALL)Matcher matcher = pattern.matcher(response);while (matcher.find()) {try {String eventJson = matcher.group(1).trim();// 處理可能的UTF-8 BOM頭if (eventJson.startsWith("\uFEFF")) {eventJson = eventJson.substring(1);}JSONObject jsonResponse = new JSONObject(eventJson);String eventType = jsonResponse.optString("event");if ("message_end".equals(eventType)) {vars.put("response_type", "智能體執行成功");vars.put("error_msg", "智能體執行成功");vars.put("isExist", "true");} else if ("error".equals(eventType)) {              vars.put("response_type", "智能體執行失敗");String errorMsg = jsonResponse.get("message");vars.put("error_msg", errorMsg);vars.put("isExist", "false");}} catch (JSONException e) {log.warn("SSE事件JSON解析失敗,跳過該事件: " + vars.get("appName"));}}
}SampleResult prev = ctx.getPreviousResult();String response = prev.getResponseDataAsString();//添加APPID信息
vars.put("APPID",vars.get("appId"));//每次重置isExist的值,避免上次結果影響本次
vars.put("isExist", "true");try {if (!isStreamingResponse(response)) {handleNonStreamingResponse(response, prev);} else {handleStreamingResponse(response, prev);}
} catch (Exception e) {log.error("處理響應失敗!", e);prev.setSuccessful(false);
}

handleStreamingResponse方法:
對每次符合要求的數據進行處理和判斷

// 正則表達式,確保匹配完整JSON
Pattern pattern = Pattern.compile(“data:\s*(\{[^{}]*\})”, Pattern.DOTALL)
Matcher matcher = pattern.matcher(response);

data:\s*
匹配字符串 “data:”,后面跟 0個或多個空白字符(\s* 包括空格、換行符等)。

(\{[^{}]*\})
\{ 匹配左花括號 {({ 需要轉義)。
[^{}]* 匹配 任意字符(除了 { 和 })0次或多次,確保匹配的是 單層花括號 的內容。
\} 匹配右花括號 }。
() 表示捕獲組,最終提取的是花括號內的內容。

Pattern.DOTALL
讓 . 匹配 包括換行符在內的所有字符,確保多行文本也能被正確匹配。
.
Matcher matcher = pattern.matcher(response);
用編譯好的正則模式 pattern 去匹配輸入的字符串 response。
matcher 對象可以用于查找、提取符合正則規則的部分。

while (matcher.find()) {
try {
String eventJson = matcher.group(1).trim();

matcher.find() 每次找到一個匹配項后,會移動內部指針,直到所有匹配項被遍歷完。

matcher.group(1) 提取正則中 第一個捕獲組(即 ({[^{}]*}) 匹配的 {…} 部分)。

2.4.3 JSR JSR223 Assertion

進行斷言處理,處理需要輸出的信息

// 斷言
if ("false".equals(vars.get("isExist"))) {// 獲取智能體名稱String appName = vars.get("appName");// 獲取具體失敗類型String respone_type = vars.get("response_type");// 獲取error_messageString error_message = vars.get("error_msg");// 獲取APPIDString appId = vars.get("APPID");//執行失敗AssertionResult.setFailure(true); // 標記斷言失敗AssertionResult.setFailureMessage(appName + "\n\t" + " 智能體ID:" + appId + "\n" + "\t 錯誤原因:"+ respone_type + "\n" + "\t error_message:" + error_message);// 添加到標簽列//prev.setSampleLabel(vars.get("respone_type")) // 修改響應消息為message變量的內容prev.setResponseMessage(respone_type);// 添加調試信息log.info("智能體名稱:", appName);log.info("智能體ID:", appId);log.info("錯誤原因:", respone_type);log.info("error_message:", error_message);
}

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

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

相關文章

<<運算符重載 和 c_str() 的區別和聯系

例題 文章開始之前我們看下以下代碼&#xff0c;你能精準的說出正確的輸出結果并知道其原理嗎&#xff1f; void test() {string s1("hello world");cout << s1 << endl;//cout << s1.c_str() << endl;//const char* p1 "xxxx"…

python web flask專題-Flask入門指南:從安裝到核心功能詳解

Flask入門指南&#xff1a;從安裝到核心功能詳解 Flask作為Python最流行的輕量級Web框架之一&#xff0c;以其簡潔靈活的特性廣受開發者喜愛。本文將帶你從零開始學習Flask&#xff0c;涵蓋安裝配置、項目結構、應用實例、路由系統以及請求響應處理等核心知識點。 1. Flask安…

一種C# 的SM4 的 加解密的實現,一般用于醫療或者支付

一種C# 的SM4 的 加解密的實現 一般用于醫療或者支付 加密 string cipherText SM4Helper.Encrypt_test(data, key); public static string Encrypt_test(string plainText, string key) { byte[] keyBytes Encoding.ASCII.GetBytes(key); byte[] input…

“軒轅杯“云盾礪劍CTF挑戰賽 Web wp

文章目錄 ezflaskezjsezrceezssrf1.0簽到ezsql1.0ez_web1非預期預期解 ezflask ssti, 過濾了一些關鍵詞, 繞一下就行 name{{url_for["__globals__"]["__builtins__"]["eval"]("__tropmi__"[::-1])(os)["po""pen"…

Matlab快速上手五十六:詳解符號運算里假設的用法,通過假設可以設置符號變量的取值范圍,也可以通過假設設置變量屬于集合:整數、正數和實數等

1.符號變量中假設的概念 在符號數學工具箱中&#xff0c;符號變量默認范圍是全體復數&#xff0c;也就是說&#xff0c;符號運算是在全體復數域進行的&#xff0c;若需要運算中&#xff0c;不使用全體復數域&#xff0c;可以為變量設定取值范圍&#xff0c;這就用到了假設&…

【python實用小腳本-79】[HR轉型]Excel難民到數據工程師|用Python實現CSV秒轉JSON(附HRIS系統對接方案)

場景故事&#xff1a;從手動復制粘貼到自動化數據流轉 "Kelly&#xff0c;我們需要把3000名員工的考勤數據導入新HR系統&#xff0c;今天能完成嗎&#xff1f;"去年這個時候&#xff0c;作為HRIS項目負責人的我&#xff0c;面對這個需求時第一反應是打開Excel開始手…

數據透視:水安 B 證如何影響水利企業的生存指數?

某大數據公司提取了 3000 家水利企業的經營數據&#xff0c;一組關聯分析令人震驚&#xff1a;B 證配備率與企業利潤率的相關系數達 0.67—— 這意味著持證率每提升 10%&#xff0c;企業利潤率平均提高 4.2 個百分點。當我們用數據解剖這本紅本本&#xff0c;會發現它像一根無形…

從零搭建上門做飯平臺:高并發訂單系統設計

你知道為什么聰明人都在搶著做上門做飯平臺嗎&#xff1f;因為這可能是餐飲行業最后一片藍海&#xff01;傳統餐飲還在為房租人工發愁時&#xff0c;上門私廚已經輕裝上陣殺出重圍。不需要門店租金&#xff0c;不用養服務員&#xff0c;廚師直接上門服務&#xff0c;成本直降60…

openpi π? 項目部署運行邏輯(四)——機器人主控程序 main.py — aloha_real

π? 機器人主控腳本都在 examples 中&#xff1a; 可以看到包含了多種類機器人適配 此筆記首先記錄了 aloha_real 部分 aloha_real 中&#xff0c;main.py 是 openpi ALOHA 平臺上“主控執行入口”&#xff0c;負責&#xff1a; 建立與推理服務器&#xff08;serve_policy.…

利用 Python 爬蟲獲取唯品會 VIP 商品詳情:實戰指南

在當今電商競爭激烈的環境中&#xff0c;VIP 商品往往是商家的核心競爭力所在。這些商品不僅代表著品牌的高端形象&#xff0c;更是吸引高價值客戶的關鍵。因此&#xff0c;獲取 VIP 商品的詳細信息對于市場分析、競品研究以及優化自身產品策略至關重要。Python 作為一種強大的…

鴻蒙桌面快捷方式開發

桌面快捷方式開發實戰 [參考文檔] (https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-desktop-shortcuts) 在module.json5配置文件中的abilities標簽下的metadata中設置resource屬性值為$profile:shortcuts_config&#xff0c;指定應用的快捷方式配置文件&…

3分鐘學會跨瀏覽器富文本編輯器開發:精準光標定位+內容插入(附完整代碼)

一、痛點直擊&#xff1a;傳統編輯器的三大坑 作為前端開發&#xff0c;你是否遇到過以下靈魂拷問&#xff1f; ? 為什么Firefox光標能精準定位&#xff0c;IE卻永遠跳轉到開頭&#xff1f;? 圖片上傳后如何保證插入位置不偏移&#xff1f;? 跨瀏覽器兼容測試時&#xff0…

RK3562 Linux-5.10 內核HUSB311 Type-C 控制器芯片調試記錄

硬件原理&#xff1a; 1. type C 接口&#xff1a; 1.1 HUSB311芯片&#xff0c; CC1和CC2 邏輯接到HUSB311 上面&#xff0c; 接I2C0組和USBCC_INT_L USBCC_INT_L 接到GPIO0_A6 做為CC的邏輯中斷 1.2 TYPEC_DP/TYPEC_DM 接到ARM 端的USB3.0 OTG上面 1.2 TYPEC_RX1P/TYPEC…

深入理解Java中的BigDecimal:高精度計算的核心工具

精心整理了最新的面試資料和簡歷模板&#xff0c;有需要的可以自行獲取 點擊前往百度網盤獲取 點擊前往夸克網盤獲取 引言 在Java編程中&#xff0c;處理浮點數運算時可能會遇到精度丟失的問題。例如&#xff1a; System.out.println(0.1 0.2); // 輸出&#xff1a;0.30000…

大模型微調(面經總結)

持續更新中 一、LORA篇1、介紹一下Lora的原理2、LoRA 是為了解決什么問題提出的&#xff1f;哪些模型適合用 LoRA 微調&#xff1f;什么是低秩分解&#xff1f;**低秩分解&#xff1a;用小矩陣逼近大矩陣** 3、LoRA初始化4、LoRA初始化秩 r 是怎么選的&#xff1f;為什么不選其…

Camera相機人臉識別系列專題分析之一:人臉識別系列專題SOP及理論知識介紹

【關注我&#xff0c;后續持續新增專題博文&#xff0c;謝謝&#xff01;&#xff01;&#xff01;】 上一篇我們講了&#xff1a;內存泄漏和內存占用拆解系列專題 這一篇我們開始講&#xff1a; Camera相機人臉識別系列專題分析之一&#xff1a;人臉識別系列專題SOP及理論知識…

【Elasticsearch】PUT` 請求覆蓋式更新

是的&#xff0c;Elasticsearch 中的 PUT 請求是覆蓋式的。當你使用 PUT 請求向索引中寫入文檔時&#xff0c;如果文檔已經存在&#xff0c;Elasticsearch 會完全替換整個文檔的內容&#xff0c;而不是進行部分更新。 覆蓋式的具體行為 - 文檔存在時&#xff1a;PUT 請求會用新…

計算機系統結構-第4章-數據級并行

數據集并行的概念: 并行場景1: 對不同數據執行相同的操作: 串行執行: 可以同時進行: 可以嘗試一個多條指令,多核執行 引入: SISD: 單核,單線程,串行執行,這樣耗時 MIMD: 多核,多線程,并行執行,一條指令多次重復,變成了MIMID 存在的問題: 在標量CPU流水線中&#xff0…

重新安裝解決mac vscode點擊不能跳轉問題

依次執行以下過程 刪除vscode程序 刪除vscode的緩存文件夾(xxx表示你的用戶名) /Users/xxx/Library/Application Support/Code 重新安裝vscode 這時候你會反向可以跳轉項目內的import 文件以及自定義函數。但是import安裝的包還不能點擊跳轉 配置python環境 如果你電腦沒有安…

題目 3334: 藍橋杯2025年第十六屆省賽真題-園藝

題目 3334: 藍橋杯2025年第十六屆省賽真題-園藝 時間限制: 2s 內存限制: 192MB 提交: 129 解決: 37 題目描述 小藍從左到右種了 n 棵小樹&#xff0c;第 i 棵樹的高度為 hi &#xff0c;相鄰樹的間隔相同。 小藍想挪走一些樹使得剩下的樹等間隔分布&#xff0c;且從左到右高度逐…