
本文详解如何在 jmeter 多线程组 + 多远程负载机(lg)场景下,通过属性传递与 __machineip() 函数配合,实现仅让第二个线程组在指定单台 lg 上执行,避免因 -j 与 -g 混用导致的属性不可见问题。
本文详解如何在 jmeter 多线程组 + 多远程负载机(lg)场景下,通过属性传递与 __machineip() 函数配合,实现仅让第二个线程组在指定单台 lg 上执行,避免因 -j 与 -g 混用导致的属性不可见问题。
在 JMeter 分布式压测中,常需对不同业务模块施加差异化负载策略:例如,主线程组(TG1)需均匀分散至全部 3 台 Windows 负载机(LG),而辅助线程组(TG2)仅需在其中一台 LG(如 10.0.0.3)上运行。此时,若直接在 If Controller 中硬编码 IP(如 "${__machineIP()}"=="10.0.0.3"),虽可临时生效,但缺乏灵活性,无法适配 GitLab CI/CD 环境下的动态配置需求。
正确做法是将目标 LG 的 IP 作为全局属性(Global Property)传入,并确保其在所有远程节点上均可被 If Controller 解析。关键在于区分 JMeter 的两类属性机制:
- -Jkey=value:仅在本地(master)JVM 中设置系统属性(System Property),不会同步到远程 LG 节点;
- -Gkey=value:设置全局属性(Global Property),会自动广播至所有启用的远程 LG,且可在任何线程组、任何控制器中通过 ${__P(key)} 或 ${__property(key)} 引用。
因此,原命令中:
-JLG_TG2=10.0.0.3 # ❌ 错误:该属性仅存在于 master,LG 节点无法读取
应修正为:
-GLG_TG2=10.0.0.3 # ✅ 正确:全局属性,所有 LG 均可访问
同时,在 TG2 的 If Controller 中,表达式需使用标准函数语法:
"${__machineIP()}" == "${__P(LG_TG2)}"
⚠️ 注意:__machineIP() 返回当前 LG 的实际 IP 地址(字符串),__P() 用于安全读取全局属性值;双引号包裹确保字符串比较,避免空值或类型隐式转换异常。
完整推荐命令示例(GitLab CI 中):
jmeter.bat -n \ -t "C:\GitLab-Runner\Builds\test.jmx" \ -R 10.0.0.1,10.0.0.2,10.0.0.3 \ -l "results.jtl" \ -GNoOfThreads_TG1=1 -GRampUpPeriod_TG1=3 -GNoOfLoops_TG1=2 \ -GNoOfThreads_TG2=1 -GRampUpPeriod_TG2=1 -GNoOfLoops_TG2=2 \ -GLG_TG2=10.0.0.3
✅ 验证建议:
- 在 TG2 内添加一个 Debug Sampler + View Results Tree(仅调试时启用),检查 vars.get("JMeterThread.last_sample_ok") 及日志中 If Controller 的求值结果;
- 启用 JMeter 日志级别为 DEBUG,观察 jmeter.log 中是否出现 "Evaluating condition: ${__machineIP()} == ${__P(LG_TG2)}" 及其计算结果;
- 确保所有 LG 的 jmeter-server.bat 已重启(或使用 -Djava.rmi.server.hostname=xxx 显式指定绑定 IP),避免因 RMI 地址解析异常导致 __machineIP() 返回 127.0.0.1。
总结:分布式场景下,跨节点生效的配置必须使用 -G 传递全局属性,-J 仅适用于 master 本地逻辑。结合 __machineIP() 进行 LG 级条件路由,是实现精细化流量调度的可靠模式——既保持脚本复用性,又满足 CI/CD 动态化部署要求。










