JMeter WebSocket测试如何跨线程组复用已有连接并控制执行顺序
JMeter WebSocket 跨线程组执行顺序控制与连接复用方案
核心问题根因
- WebSocket连接无法跨线程组复用:JMeter WebSocket Samplers 建立的连接绑定在所属线程的上下文变量中,不同线程组属于独立线程上下文,若依赖测试计划的「连续运行线程组」选项,上一个线程组执行完后线程会直接销毁,持有的WebSocket连接也会同步释放,后续线程组自然无法访问已建立的连接。
- 执行顺序错乱:默认配置下多个线程组并行启动,没有同步阻塞机制时,请求执行顺序完全受CPU调度影响,会出现Participant端先执行、读取到上一轮测试遗留旧sessionId的问题。
可直接落地的配置步骤
基础配置修正
- 不要单独创建第三个线程组存放send请求:send是Presenter端基于自有WebSocket连接的写操作,直接归属到Presenter线程组即可,从根源上避免跨线程复用连接的需求。
- 取消勾选测试计划的
run thread groups consecutively(连续运行线程组)选项,两个线程组保持并行启动模式,线程数均设为1,循环次数按实际测试轮次配置。 - 测试计划根节点新增JSR223 Sampler,测试启动时先清空历史缓存的sessionId,避免旧值干扰,代码如下:
props.remove("sessionId") props.remove("sessionReadyLatch") props.remove("participantReadyLatch") props.remove("sendCompleteLatch")
基于CountDownLatch实现严格顺序控制
用JDK自带的CountDownLatch做线程间同步阻塞,不需要额外安装插件,即可严格按指定流程执行:
- Presenter线程组第一阶段:Login -> Connect -> 创建session的Subscribe请求
保留原有sessionId解析逻辑,在创建session请求的JSR223 PostProcessor中追加同步逻辑,通知Participant端session已生成:import groovy.json.JsonSlurper; import java.util.concurrent.CountDownLatch; def response = prev.getResponseDataAsString(); String[] res = response.split(); def json = new JsonSlurper().parseText(res[res.size() -1]); vars.put("sessionUUID", json.data.sessionUUID); props.put("sessionId", vars.get("sessionUUID")); // 触发session就绪通知 CountDownLatch sessionReadyLatch = new CountDownLatch(1); props.put("sessionReadyLatch", sessionReadyLatch); sessionReadyLatch.countDown(); - Participant线程组前置等待
在Connect请求之后、Subscribe请求之前新增JSR223 Sampler,阻塞等待Presenter生成新sessionId后再执行订阅,避免拿旧值:import java.util.concurrent.CountDownLatch; CountDownLatch sessionReadyLatch = props.get("sessionReadyLatch"); // 最长等待10秒,超时直接抛错终止流程 if (sessionReadyLatch != null) { boolean awaitResult = sessionReadyLatch.await(10, java.util.concurrent.TimeUnit.SECONDS); if (!awaitResult) { prev.setSuccessful(false); prev.setResponseMessage("Wait sessionId generate timeout"); return; } } // 读取本轮新生成的sessionId存入当前线程变量 String currentSessionId = props.get("sessionId"); if (currentSessionId == null || currentSessionId.trim().isEmpty()) { prev.setSuccessful(false); prev.setResponseMessage("Got empty sessionId"); return; } vars.put("sessionUUID", currentSessionId); - Participant线程组第一阶段:Connect -> Subscribe
订阅流程执行完成后,在Subscribe请求后新增JSR223 PostProcessor,通知Presenter端自己已完成订阅准备:import java.util.concurrent.CountDownLatch; CountDownLatch participantReadyLatch = new CountDownLatch(1); props.put("participantReadyLatch", participantReadyLatch); participantReadyLatch.countDown(); - Presenter线程组第二阶段等待
在创建session请求之后、send请求之前新增JSR223 Sampler,阻塞等待Participant完成订阅后再发消息:import java.util.concurrent.CountDownLatch; CountDownLatch participantReadyLatch = props.get("participantReadyLatch"); if (participantReadyLatch != null) { boolean awaitResult = participantReadyLatch.await(10, java.util.concurrent.TimeUnit.SECONDS); if (!awaitResult) { prev.setSuccessful(false); prev.setResponseMessage("Wait participant subscribe timeout"); return; } } - Presenter线程组执行send请求
等待完成后直接执行WebSocket Single Write Sampler发送消息,因为连接是当前线程创建的,可以直接正常复用,不存在连接找不到的问题。发送完成后新增JSR223 PostProcessor,通知Participant端消息已发出,可以开始时延统计:import java.util.concurrent.CountDownLatch; CountDownLatch sendCompleteLatch = new CountDownLatch(1); props.put("sendCompleteLatch", sendCompleteLatch); sendCompleteLatch.countDown(); - Participant线程组启动时延测试
在Subscribe请求之后、包含WebSocket Single Read Sampler的循环控制器之前新增JSR223 Sampler,等待消息发送完成的通知,收到通知后再启动循环读消息、计算时延:import java.util.concurrent.CountDownLatch; CountDownLatch sendCompleteLatch = props.get("sendCompleteLatch"); if (sendCompleteLatch != null) { boolean awaitResult = sendCompleteLatch.await(10, java.util.concurrent.TimeUnit.SECONDS); if (!awaitResult) { prev.setSuccessful(false); prev.setResponseMessage("Wait presenter send message timeout"); return; } } - 每轮测试流程结束后,两个线程组都主动调用WebSocket Close Sampler断开当前连接,清空props中存的latch对象,避免下一轮测试受干扰。
注意事项
- 不要尝试把WebSocket连接对象存入props跨线程传递:连接对象绑定了创建它的线程上下文,跨线程调用会出现IO状态异常、连接意外断开的问题,遵循哪个线程创建连接,哪个线程负责该连接的读写原则即可完全规避这类问题。
- 所有等待逻辑都必须设置超时时间,不要无限阻塞,避免测试流程卡死。
- 多轮循环测试时,每轮结束后必须清空上一轮生成的latch和sessionId缓存,避免状态污染。
内容的提问来源于stack exchange,提问作者Zhang
相关产品推荐
相关产品推荐

