概要
大模型业务接口,通常是SSE协议,因为SSE协议的特点,通过Jmeter的http请求,只能获取“完全响应”的指标,无法获取大模型的“首token响应”指标,网上看到的哪些自称是能获得该指标,往往都是通过首token在响应字节流中所处的位置来预估响应时间,这个是非常不准确的。因为每个token直接的间隔时间是不定的。而本次通过jmeter的JSR223 Sampler请求进行模拟发送SSE请求,可以及时而准确的记录“首token响应”,“完全响应”等指标。
原理
主 JSR223 Sampler 只负责网络读写与变量输出,不涉及主 SampleResult 生命周期,通过主 JSR223 Sampler 下JSR223 后置处理程序的 “prev.setIgnore()”避免聚合报告中展示主JSR223 Sampler 时间。
两个 Transaction Controller 里的 Dummy Sampler 会以我们脚本计算的耗时/成功状态生成两条独立的聚合记录。
Jmeter 结构目录
提示:jmeter配置的组件

Jmeter 聚合报告
提示:首token响应:自定义的,也可以自定义关键字判断;完全响应:SSE请求完成该响应事务

Jmeter 输出日志

Jmeter 各组件配置

提示:JSR223 后置处理程序,主要为了不在聚合报告中体现上级的JSR223 请求

事务控制两个基本相同,就只粘贴一个




主JSR223 Sampler 源码
import java.net.Socket
import java.io.*
import java.nio.charset.StandardCharsets
// 配置参数
def CAF_WEB_SESSION = "ZDJh******************I5"
def HOST = "192.168.1.100"
def PORT = 5200
def REQ_EVENTS = 5 // 出现第REQ_EVENTS个响应块,就认为关键词响应成功
def SOCKET_TIMEOUT = 120000 // 120秒超时
def QUESTION = "我是谁?"
def KEY_WORD = "第5个响应块"
def FINISH_WORD = "data: EOF"
// 事务名称
def KEY_WORD_TRANSACTION = "智能问答_关键词响应"
def FINISH_WORD_TRANSACTION = "智能问答_全部响应"
// 将所有在函数中使用的变量设置为全局变量
binding.setVariable("CAF_WEB_SESSION", CAF_WEB_SESSION)
binding.setVariable("HOST", HOST)
binding.setVariable("PORT", PORT)
binding.setVariable("QUESTION", QUESTION)
binding.setVariable("KEY_WORD", KEY_WORD)
binding.setVariable("REQ_EVENTS", REQ_EVENTS)
binding.setVariable("FINISH_WORD", FINISH_WORD)
binding.setVariable("KEY_WORD_TRANSACTION", KEY_WORD_TRANSACTION)
binding.setVariable("FINISH_WORD_TRANSACTION", FINISH_WORD_TRANSACTION)
// 状态变量
binding.setVariable("keyWordTransactionStarted", false)
binding.setVariable("keyWordTransactionCompleted", false)
binding.setVariable("finishWordTransactionStarted", false)
binding.setVariable("finishWordTransactionCompleted", false)
binding.setVariable("resourcesCleaned", false)
// 开始事务计时
def startTransaction(transactionName) {
vars.put(transactionName + "_startTime", System.currentTimeMillis().toString())
log.info("【" + transactionName + "】事务已开始...")
}
// 结束事务计时
def endTransaction(transactionName, status) {
def startTime = vars.get(transactionName + "_startTime")
if (startTime) {
def duration = System.currentTimeMillis() - Long.parseLong(startTime)
log.info("【" + transactionName + "】事务已结束,耗时: " + duration + "ms,状态: " + (status ? "PASS" : "FAIL"))
// 将事务耗时/状态写入 JMeter 变量,供 Dummy Sampler 使用
if (transactionName == binding.getVariable("KEY_WORD_TRANSACTION")) {
vars.put("KW_DURATION_MS", String.valueOf(duration))
vars.put("KW_SUCCESS", String.valueOf(status))
} else if (transactionName == binding.getVariable("FINISH_WORD_TRANSACTION")) {
vars.put("FINISH_DURATION_MS", String.valueOf(duration))
vars.put("FINISH_SUCCESS", String.valueOf(status))
}
}
}
// 结束所有未完成的事务
def endAllTransactions(status) {
// 结束关键词事务
if

最低0.47元/天 解锁文章
547

被折叠的 条评论
为什么被折叠?



