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");
    
    // 正则表达式,确保匹配完整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);
}


<think>好的,用户想了解嵌入式边缘服务器的稳定性、性能测试方法、工具和最佳实践。首先,我需要回忆一下嵌入式系统测试的相关知识,并结合用户提供的引用内容来组织回答。 用户提到的引用中有测试设备如示波器、逻辑分析仪(引用[1]),这可能用于监测硬件层面的稳定性。另外,ADD方法(引用[2])涉及质量属性场景,可能和测试场景设计有关。picoserve(引用[3])作为嵌入式HTTP服务器,可能涉及软件层面的测试。电源管理部分(引用[4])可能影响稳定性,需要测试电源波动情况。 首先,稳定性测试需要考虑长时间运行、异常恢复、环境干扰等因素。硬件方面需要监测温度、电压等,软件方面需要压力测试和故障注入。性能测试可能包括处理能力、延迟、资源使用率等指标。工具方面,可能需要用到负载生成工具(如JMeter)、监控工具(Prometheus)、硬件测试设备(示波器)以及嵌入式专用的框架(如picoserve提到的测试工具)。 最佳实践方面,引用[2]的ADD方法可以指导测试场景的设计,确保覆盖关键质量属性。引用[4]提到的电源管理优化可能需要在测试中模拟不同的电源状况。此外,持续集成和自动化测试也是重要实践。 需要确保回答结构清晰,分步骤说明方法、工具和实践,并适当引用提供的资料。同时,用户可能希望了解具体的工具名称和使用方法,以及如何结合硬件和软件进行综合测试。还要注意生成相关问题,引导用户深入探讨。</think>### 嵌入式边缘服务器稳定性与性能测试方法 #### 一、稳定性测试方法 1. **长时间运行测试** - 模拟持续负载运行(如7×24小时),监测内存泄漏、线程死锁、资源耗尽等问题,使用工具如$stress-ng$施加压力[^1]。 - 硬件层面通过示波器监测电压波动,验证HT7333等低压差稳压器的电源稳定性(引用[4])。 2. **异常恢复测试** - 模拟网络中断、电源瞬断等故障,验证看门狗机制和自动重启功能。 - 结合逻辑分析仪记录系统崩溃时的硬件信号(引用[1])。 3. **环境适应性测试** - 通过温控箱模拟高低温循环(-40℃~85℃),检测硬件热稳定性。 - 使用频谱分析仪验证电磁干扰下的通信稳定性(引用[1])。 #### 二、性能测试方法 1. **基准性能测试** - 测量每秒请求处理量(RPS)、延迟(Latency)等指标,工具如$JMeter$或$wrk$。 - 对picoserve等嵌入式HTTP服务器进行并发连接测试(引用[3])。 2. **资源使用率分析** - 监测CPU占用率、内存消耗(如FreeRTOS的堆栈分析工具)。 - 通过$perf$或$SystemView$追踪任务调度效率。 3. **服务质量验证** - 测试WebSocket连接稳定性、SSE事件推送延迟(引用[3])。 - 验证JSON解析与响应效率,对比不同压缩算法的影响。 #### 三、推荐工具列表 | 工具类型 | 工具示例 | 适用场景 | |----------------|----------------------------|----------------------------| | 负载生成 | JMeter, Locust, wrk | HTTP接口压力测试 | | 硬件监测 | 示波器、逻辑分析仪(引用[1]) | 电源/信号完整性分析 | | 性能分析 | Prometheus+Grafana | 资源使用率可视化 | | 嵌入式专用 | Pytest-embedded, Renode | 微控制器单元测试 | #### 四、最佳实践 1. **基于ADD方法设计测试场景** - 根据质量属性(如可用性、性能)定义测试用例(引用[2]),例如: $$ \text{场景}=(\text{刺激源: 高并发请求},\ \text{响应: 延迟} < 100\text{ms}) $$ 2. **分层测试策略** - 硬件层:电源噪声测试(引用[4])+ 信号完整性验证 - 系统层:RTOS任务调度分析 - 应用层:picoserve的HTTP请求处理极限测试(引用[3]) 3. **自动化与持续集成** - 使用GitLab CI/CD集成硬件在环(HIL)测试 - 通过故障注入框架(如Chaos Mesh)模拟边缘网络抖动
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值