JMeter MQTT 压测脚本:让脚本跟着点位表走
GUI 拖出来的 JMX 只能用一次,点位一变就得重拖。把它变成"数据驱动的生成器",压测资产才能真正沉淀下来。
痛点:JMX 是二进制资产,改动成本极高
最初的压测脚本是 GUI 录出来的:几个 Thread Group、MQTT Connect、Timer 一个个手动连。问题很直接:
- 9 个光伏站点,每站一套脚本,改一次全靠复制粘贴;
- 点位增删要在 GUI 里逐个操作,JMX 是 XML 但没人敢手改;
- 脚本合并时冲突不断,版本管理形同虚设。
解法:脚本生成器 + 四个数据文件
把"结构"交给代码,把"数据"交给 txt 文件。数据源拆成四份,职责单一:
储能设备.txt # device_sn / gateway_sn / 点位归属
储能点位.txt # thirdId / 数据类型 / 量程
光伏设备.txt
光伏点位.txt
Topic 命名规范要统一
点位主题是这个场景里最容易出错的地方。规范:
/dg/get/{场景码}/{设备标识}/{点位标识}
# 例:/dg/get/06/pcs01/SOC
场景码区分业务(06 储能、07 光伏),点位标识用短名(PCSzt、SOC)而不是协议里的数字索引——短名可读、便于与文档对照,出问题时一眼定位。
每台设备一个独立 Thread Group
不要把所有设备塞进一个线程组。做法是每设备一个 Thread Group,并错峰 2 秒启动:
ThreadGroup(
name=f"device-{device_sn}",
scheduler=True,
# ... 循环配置
)
# 在前置 sampler 中加入启动延迟,避免 broker 瞬时连接风暴
JSR223Sampler(code="Thread.sleep(2000 * %d)" % device_index)
同时启停会让 broker 连接建立阶段失真(TCP 握手排队、Broker 侧限流),压出来的数据没有可比性。
payload 模板化
报文结构固定,只有值在变,用 JSR223 PreProcessor 动态生成:
String body = String.format(
'{"devId":"%s","data":{"%s":%s,"ts":%d}}',
vars.get("device_sn"), point_name, randomValue(), System.currentTimeMillis()
);
vars.put("payload", body);
一个必须记住的坑:中文乱码
Windows 下用 jmeter.bat 跑带中文的 JMX,控制台与报告会出现乱码。原因是批处理默认 GBK 编码。解法很简单——用官方提供的 bin/JMeter-UTF8.bat,不要自己另造脚本。
两套脚本的取舍
多站合并脚本适合看整体水位,单站脚本适合定位单设备问题。两者都要有,但必须由同一个生成器产出,否则半年后两份脚本就分叉了。
给脚本加自检
压测前先跑一轮小流量自检:订阅端确认收到了每个点位至少一条消息、payload 能反序列化、时间戳在合理区间。数据都对再压,否则压出来的只是一堆无效连接。