JMeter技术问询:如何按登录名匹配读取CSV关联患者数据
嘿,针对你的JMeter负载测试需求,我有两个无需额外插件、纯原生元件的实现方案,完美解决“每个医生线程只读取自己关联患者数据”的问题,不用单独为每个账号建CSV:
方案一:预加载+分组过滤(推荐,大数据量友好)
这个思路是先把csv2的所有患者数据一次性加载到内存,按loginName分组,然后每个医生线程直接取自己分组下的患者列表,性能拉满,适合患者数据多的场景。
步骤拆解:
先配置医生账号的CSV(csv1)
给线程组加个CSV Data Set Config,设置如下:- 文件名:选你的csv1实际路径
- 变量名:
doctorLogin, doctorPwd(对应登录名、密码) - 分隔符:逗号(和你的csv实际分隔符一致)
- 循环到文件末尾时:不循环,停止线程(确保每个线程拿到唯一的医生账号)
- 共享模式:
Current thread group
预加载csv2并分组存到全局属性
在测试计划的最顶部(根节点)加个JSR223 Test Plan,语言选Groovy(JMeter里性能最好的脚本语言),贴下面的代码:// 替换成你的csv2实际路径 def csvFile = new File("C:/testdata/csv2.csv") // 用Map按loginName分组存患者数据 def patientGroups = [:].withDefault { [] } // 跳过表头(如果csv2没有表头,就把这行删掉!) csvFile.readLines().drop(1).each { line -> def cols = line.split(",") // 分隔符和你的csv一致 patientGroups[cols[2]] << [name: cols[0], id: cols[1]] } // 把分组数据存到JMeter全局属性,所有线程都能访问 props.put("patientGroups", patientGroups)给当前线程初始化专属患者列表
在你的Runtime Controller里面加个JSR223 PreProcessor,语言选Groovy,代码:// 拿到当前线程的医生登录名 def myLogin = vars.get("doctorLogin") // 从全局属性取自己的患者列表 def myPatients = props.get("patientGroups").get(myLogin, []) // 存到当前线程变量,同时初始化遍历索引 vars.putObject("myPatients", myPatients) vars.put("currentPatientIdx", "0")配置While Loop的循环条件
把While Loop的Condition改成这个Groovy函数:${__groovy(vars.getObject("myPatients").size() > vars.get("currentPatientIdx") as int,)}意思就是:只要还有没遍历的患者,就继续循环。
循环内读取当前患者数据
在While Loop里加个JSR223 PreProcessor,代码:def patients = vars.getObject("myPatients") def idx = vars.get("currentPatientIdx") as int def currentPat = patients[idx] // 把患者数据存成线程变量,后面请求直接用${PatientName}、${PatientId} vars.put("PatientName", currentPat.name) vars.put("PatientId", currentPat.id) // 索引+1,准备下一个患者 vars.put("currentPatientIdx", (idx + 1).toString())
方案二:逐行读取+过滤(小数据量友好)
如果你的患者数据不多,这个方案配置更简单,不用预加载,直接逐行读csv2,直到找到和当前医生匹配的记录:
步骤拆解:
同样先配置csv1的CSV Data Set Config(和方案一的步骤1完全一样)
配置csv2的CSV Data Set Config
加个新的CSV Data Set Config,设置:- 文件名:选csv2实际路径
- 变量名:
tempPatName, tempPatId, tempLogin - 分隔符:逗号
- 循环到文件末尾时:循环读取(直到找到匹配的)
- 停止线程:
False - 共享模式:
All threads
配置While Loop的过滤条件
把While Loop的Condition改成:${__groovy(!vars.get("tempLogin").equals(vars.get("doctorLogin")),)}意思是:如果当前读的csv2记录的loginName和当前医生不匹配,就继续读下一行,直到找到匹配的。
处理匹配后的患者数据
当While Loop退出时,${tempPatName}和${tempPatId}就是当前医生的患者数据了,你可以直接用,或者存成固定变量。另外建议加个计数器,防止万一没有匹配记录导致无限循环(比如设置最多读100行就停止)。
关键注意点
- 确保csv2里的
loginName和csv1的登录名完全一致(大小写、空格都不能错) - 如果csv有表头,记得在CSV Data Set Config里勾选
Ignore first line,方案一的Groovy代码也要对应跳过表头(就是那个drop(1)) - 方案一适合大数据量,因为只加载一次csv2;方案二适合小数据量,配置更快
内容的提问来源于stack exchange,提问作者Phani Bhushan Manne

