当单台压测机的硬件资源(CPU、内存、网络)不足以产生目标并发时,就需要引入分布式压测。JMeter 采用 Master-Slave 架构,由一台 Master 机统一调度多台 Slave 机共同施压,突破单机瓶颈。本文将详细讲解 Master-Slave 的工作原理、环境搭建、脚本分发策略,以及常见问题的解决方案。
一、为什么需要分布式压测?
单机压测的局限性:
- CPU 瓶颈:每增加一个虚拟线程,JMeter 都需要消耗 CPU 去管理线程状态、调度和执行计算。当线程数超过单机 CPU 核心处理能力时,线程调度开销会急剧增加,导致响应时间变长,TPS 上不去。
- 内存瓶颈:大量取样器结果、监听器数据(尤其是"查看结果树")会占用大量堆内存,容易触发频繁的 GC 停顿,影响压测引擎的稳定性,甚至导致 OutOfMemoryError。
- 网络瓶颈:单机网卡带宽有限(例如 1Gbps)。在高并发场景下,大量请求和响应数据可能占满网络带宽,成为性能瓶颈,无法真实模拟海量用户。
- 端口数限制:单台机器的可用端口数有限(通常约 28000 个临时端口),当模拟大量长连接或高并发短连接时,可能耗尽端口资源。
- 无法模拟真实地理分布:对于需要测试 CDN、全球负载均衡或不同地域用户访问体验的场景,单机无法模拟来自不同网络环境的流量。
分布式压测正是为了解决以上单机瓶颈而生。 它通过将负载分散到多台机器上执行,从而:
- 横向扩展负载能力:突破单机硬件(CPU、内存、网络、端口)上限。
- 更真实地模拟用户场景:可以从不同网络、不同地域发起请求。
- 提高测试效率和资源利用率:利用多台机器并行执行,缩短压测时长。
二、Master-Slave 架构原理
JMeter 分布式压测采用一主多从模式:
Master(调度机):负责分发测试脚本(JMX 文件)给所有 Slave、启动/停止测试、收集各 Slave 的结果并汇总展示。
Slave(执行机):接收 Master 分发的脚本,以非 GUI 模式执行测试,将结果数据回传给 Master。
关键理解:最终的总并发线程数 = 脚本中设置的线程数 × Slave 机器数量。
例如:脚本中线程组设置 100 个线程,3 台 Slave,则总并发 = 100 × 3 = 300。
三、环境准备
3.1 统一基础环境
相同版本的 JMeter:所有机器必须使用完全相同的 JMeter 版本。
相同版本的 Java:JDK 版本一致(建议 JDK 11 或 17)。
相同的插件集:如果脚本依赖第三方插件(如 Custom Thread Groups),所有 Slave 必须安装相同版本的插件。
网络互通:确保 Master 与各 Slave 之间网络通畅,防火墙开放必要端口(默认 1099、5000)。
3.2 文件一致性
测试脚本(.jmx)的绝对路径引用(如 CSV 数据文件、JAR 包)必须在各 Slave 上存在且路径一致。
推荐将所有依赖文件放在 JMeter 的 bin 目录下,或使用相对路径。
四、分布式环境搭建步骤
假设我们有一台 Master(IP: 192.168.1.100)和两台 Slave(IP: 192.168.1.101、192.168.1.102),操作系统均为 Linux。
4.1 Slave 配置
Step 1:在每台 Slave 上安装 JMeter,并确保 jmeter 命令可用。
Step 2:启动 jmeter-server 服务:
bash
cd $JMETER_HOME/bin
./jmeter-server -Djava.rmi.server.hostname=192.168.1.101 # 替换为 Slave 实际 IP
Step 3:确认服务已启动:
bash
netstat -tlnp | grep 1099 # 查看 RMI 端口是否监听
4.2 Master 配置
Step 1:编辑 Master 的 jmeter.properties 文件,指定远程 Slave 列表:
properties
remote_hosts=192.168.1.101:1099,192.168.1.102:1099
Step 2:确认网络连通性,Master 能 telnet 通 Slave 的 1099 端口。
Step 3:启动 JMeter GUI,在 "Run" 菜单中应该能看到 "Remote Start" 下出现了配置的 Slave 列表。
4.3 SSL 配置(可选)
从 JMeter 5.0 开始,默认启用 RMI SSL。如果测试环境是内网可信任网络,可以关闭 SSL 简化配置:
在 Master 和所有 Slave 的 jmeter.properties 中:
properties
server.rmi.ssl.disable=true
五、执行分布式压测
5.1 GUI 模式(调试用)
点击菜单 Run → Remote Start,可选择单个 Slave 或 Remote Start All 启动所有 Slave。
启动后,Master 会将当前打开的测试脚本分发到所有 Slave,Slave 开始执行。在 Master 上添加监听器(如聚合报告),会看到从各 Slave 汇总的数据。
⚠️ 警告:GUI 模式仅适合调试,压测执行必须使用命令行模式。
5.2 命令行模式(生产推荐)
bash
# 指定 Slave 列表
jmeter -n -t test.jmx -l result.jtl -R slave1_ip:port,slave2_ip:port
# 使用 jmeter.properties 中配置的 Slave
jmeter -n -t test.jmx -l result.jtl -r
# 指定 IP 和端口(如果在 property 中配置了端口)
jmeter -n -t test.jmx -l result.jtl -R 192.168.1.101,192.168.1.102
执行完成后,所有 Slave 的结果汇总到 Master 的 result.jtl 中。
六、脚本分发与数据文件同步策略
分布式执行中最大的坑是:Master 只是分发 JMX 文件,并不会同步 CSV 数据文件、JAR 包等其他依赖。
6.1 方案一:手动同步(适合小规模)
将测试脚本、CSV 数据文件、依赖 JAR 包手动复制到所有 Slave 的同一路径下。
6.2 方案二:共享存储(推荐)
使用 NFS 或 Samba 挂载一个共享目录,所有 Slave 的 JMeter 指向该目录。
在 jmeter.properties 中设置:
properties
将脚本路径指向共享目录
user.dir=/mnt/nfs/jmeter_workspace
6.3 方案三:使用第三方工具自动分发
Ansible:编写 playbook 批量同步文件。
rsync:rsync -avz ./scripts/ user@slave1:/opt/jmeter/scripts/
注意:如果使用 CSV 数据集进行参数化,要确保每个 Slave 上的 CSV 文件内容一致(或用分布式预取策略避免重复)。
七、分布式压测的常见问题与解决

八、实战案例:用 3 台机器压测 1000 并发
场景:目标并发 1000,单机最多支持 300 并发,因此需要 4 台 Slave(实际准备 4 台)。
测试计划配置:
线程组线程数:250
每台 Slave 执行 250 个线程
总并发 = 250 × 4 = 1000
执行命令:
bash
jmeter -n -t script.jmx -l result.jtl -R slave1,slave2,slave3,slave4
执行完成后,使用 -g 生成报告:
bash
jmeter -g result.jtl -o report/
九、性能优化建议
Master 不宜执行压力:Master 仅负责调度和汇总,建议在其 jmeter.properties 中设置 server.rmi.ssl.disable=true 并分配较少内存。
使用 CSV 格式的结果文件:XML 格式 JTL 会消耗大量网络带宽和磁盘 I/O。
关闭不必要的监听器:压测过程中不要附加"查看结果树"等开销大的组件。
Linux 系统参数调优:增大系统文件句柄数、调整内核网络参数。
十、总结
本文核心:
Master-Slave 架构原理:Master 分发脚本和调度,Slave 执行并回传结果
环境要求:版本一致、插件一致、网络互通
命令行执行是关键,GUI 仅用于调试
数据文件同步是分布式最易出错的环节