JMeter-SSE响应数据自动化

news2025/6/3 23:23:15

结构图

在这里插入图片描述

背景:

需要写一个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");
    
    // 正则表达式,确保匹配完整JSON
    Pattern 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_message
	String error_message = vars.get("error_msg");
	// 获取APPID
	String 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.coloradmin.cn/o/2386812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

泛型(1)

1.泛型的理解和好处 使用传统方法的问题分析 (1)不能对加入到集合ArrayList中的数据类型进行约束 (2)遍历的时候,需要进行类型装换,如果集合中的数量较大,对效率有影响. 使用泛型的好处 (1)使用泛型添加 (检查元素的类型,提高了安全性.) (2)减少了类型转换的次数,提高效率…

esp8266 点灯科技远程控制继电器

手机端安装点灯科技app 打开 Arduino IDE 编辑&#xff1a; #define BLINKER_WIFI #include <Blinker.h> char auth[] "点灯科技 key"; char ssid[] "wifi ID"; char pswd[] "WiFi key"; // 新建组件对象 BlinkerButton Button1(&q…

MMA: Multi-Modal Adapter for Vision-Language Models论文解读

abstract 预训练视觉语言模型&#xff08;VLMs&#xff09;已成为各种下游任务中迁移学习的优秀基础模型。然而&#xff0c;针对少样本泛化任务对VLMs进行微调时&#xff0c;面临着“判别性—泛化性”困境&#xff0c;即需要保留通用知识&#xff0c;同时对任务特定知识进行微…

使用 Cannonballs 进行实用导体粗糙度建模

在 GB/s 制度下&#xff0c;导体损耗的精确建模是高速串行链路设计成功的前提。未能对粗糙度效果进行建模可能会毁了您的一天。例如&#xff0c;图 1 显示了与测量数据相比&#xff0c;无粗糙度的 40 英寸印刷电路板 &#xff08;PCB&#xff09; 走线的模拟总损耗。总损耗是电…

Spring Boot 注解 @ConditionalOnMissingBean是什么

一句话总结&#xff1a; ConditionalOnMissingBean 是 Spring Boot 提供的一个 条件注解&#xff08;Conditional Annotation&#xff09;&#xff0c;意思是&#xff1a; 只有当 Spring 容器中 不存在 某个 Bean 时&#xff0c;当前的 Bean 或配置才会被加载。 这是一种典型的…

(先发再改)测试流程标准文档

Revision Record 修订记录 序号 修改日期 修改章节 修改描述 拟制 审批 修订版本 1 20250520 初稿 v1.0 目录 1. 文档概述... 7 1.1 文档目的... 7 1.1.1 标准化质量保障流程... 7 1.1.2.…

亚马逊SP-API开发实战:商品数据获取与操作

一、API接入准备 开发者注册&#xff1a; 登录亚马逊开发者中心申请SP-API权限 完成MWS迁移&#xff08;如适用&#xff09; 认证配置&#xff1a; # OAuth2.0认证示例 import requests auth_url "https://api.amazon.com/auth/o2/token" params { "…

行为型:策略模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、优化技巧 1、核心思想 目的&#xff1a;将算法&#xff08;行为&#xff09;抽象出来作为一系列策略类&#xff0c;使他们可以相互替换&#xff0c;使系统拥有“可插拔”扩展的能…

知识宇宙-学习篇:开源项目 README 文档该如何写?

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、README 文档的重要性1. 项目的第一印象2. 搜索引擎优化的重要载体 二、现代 RE…

YOLOv12增加map75指标

YOLOv12源码&#xff1a;https://github.com/sunsmarterjie/yolov12 第一步&#xff1a;更改Val.py文件 地址&#xff1a;该文件在yolov12-main\ultralytics\models\yolo\detect下 首先定位到def get_desc(self):这个函数上 代码修正如下&#xff1a; def get_desc(self):&q…

Avalanche 六期 Workshop 精华合集|Grant 机会、技术深度、项目实战一文回顾!

作为当前区块链技术的前沿代表&#xff0c;Avalanche 以其独特的高吞吐、低延迟、多链架构&#xff0c;为开发者提供了一种颠覆性的 Layer 1 解决方案。不同于传统的 EVM 兼容链&#xff0c;Avalanche 支持开发者自定义执行环境&#xff0c;灵活选择最适合自身业务需求的虚拟机…

【MySQL】第九弹——索引(下)

文章目录 &#x1f30f;索引(上)回顾&#x1f30f;使用索引&#x1fa90;自动创建索引&#x1fa90;手动创建索引&#x1f680;主键索引&#x1f680;普通索引&#x1f680;唯一索引&#x1f680;复合索引 &#x1fa90;查看索引&#x1fa90;删除索引&#x1f680;删除主键索引…

leetcode-295 Find Median from Data Stream

class MaxHeap {private heap: number[];constructor() {this.heap [];}// 插入元素并上浮调整push(num: number): void {this.heap.push(num);this.siftUp(this.heap.length - 1);}// 弹出堆顶元素并下沉调整pop(): number {const top this.heap[0];const last this.heap.p…

【后端高阶面经:缓存篇】37、高并发系统缓存性能优化:从本地到分布式的全链路设计

一、缓存性能优化的核心价值与分层架构 (一)缓存的多维价值体系 延迟优化 内存访问速度(100ns) vs 磁盘数据库(10ms+),性能提升10万倍+案例:电商详情页通过缓存将响应时间从500ms降至50ms吞吐提升 单机Redis可支撑10万QPS,分担数据库压力案例:秒杀系统通过缓存拦截9…

欣佰特科技| SIL2/PLd 认证 Inxpect毫米波安全雷达:3D 扫描 + 微小运动检测守护工业安全

Inxpect 成立于意大利&#xff0c;专注工业安全技术。自成立起&#xff0c;便致力于借助先进雷达技术提升工业自动化安全标准&#xff0c;解决传统安全设备在复杂环境中的局限&#xff0c;推出获 SIL2/PLd 和 UL 认证的安全雷达产品。 Inxpect 的雷达传感器技术优势明显。相较于…

【Linux】Linux 操作系统 - 18 , 重谈文件(二) ~ 文件描述符和重定向原理 , 手把手带你彻底理解 !!!

文章目录 ● 文件描述符一 、Linux 系统对文件的管理(要知道)二 、什么是文件描述符 fd ?三 、再探文件被管理过程(重要)四 、文件描述符 0 、1、21. 文件描述符的分配原则2. 提前认识三个默认打开的文件 ● 重定向原理(重要)一 、重定向现象二 、深入剖析重定向现象(重要)1…

第五十三节:综合项目实践-车牌识别系统

一、项目背景与意义 车牌识别系统(LPR)是智能交通领域的核心技术之一,广泛应用于停车场管理、违章抓拍、高速公路收费等场景。本文将通过Python+OpenCV实现一个完整的车牌识别系统,涵盖图像预处理→车牌定位→字符分割→字符识别四大核心环节。 二、系统架构设计 技术栈组…

Git Push 失败:HTTP 413 Request Entity Too Large

Git Push 失败&#xff1a;HTTP 413 Request Entity Too Large 问题排查 在使用 Git 推送包含较大编译产物的项目时&#xff0c;你是否遇到过 HTTP 413 Request Entity Too Large 错误&#xff1f;这通常并不是 Git 的问题&#xff0c;而是 Web 服务器&#xff08;如 Nginx&am…

第10章 网络与信息安全基础知识

网络概述 多模光纤的特点&#xff1a;成本低&#xff0c;宽芯线&#xff0c;聚光好&#xff0c;耗散大&#xff0c;低效&#xff0c;用于低速度、短距离的通信。 单模光纤的特点&#xff1a;成本高&#xff0c;窄芯线&#xff0c;需要激光源&#xff0c;耗散小&#xff0c;高效…

go 访问 sftp 服务 github.com/pkg/sftp 的使用踩坑,连接未关闭(含 sftp 服务测试环境搭建)

前言 最近在使用 sftp 服务时&#xff0c;被告知发起了海量的连接&#xff0c;直接把服务器搞崩&#xff0c;ip 被封了。 这是啥情况&#xff1f; golang 写的代码&#xff0c;我就正常的访问 sftp 服务&#xff0c;连接使用过后也都关闭了&#xff0c;咋会出现连接一直连着…