手把手搭建JMeter分布式压力测试环境。
一、为什么要做分布式?
单台压力机受限于CPU、内存、网络带宽,能发起的并发量有限。
JMeter分布式通过1台Master(控制机)+ 多台Slave(负载机) 的方式,把压力分散到多台机器上,由Master统一收集结果,从而模拟海量并发。
架构
Master (192.168.1.10) 发送指令给 Slave1 (192.168.1.20),Slave2 (192.168.1.30), Slave3 (192.168.1.40)
Master 不执行测试(也可以执行),仅负责把测试计划下发到各 Slave,Slave 执行后把结果返回 Master。
二、环境准备
1. 机器配置建议
操作系统:Linux(CentOS/Ubuntu 等)或 Windows 均可,集群内系统可以不同。
网络:所有机器必须处于同一局域网或网络互通,云服务器需配置安全组放通端口。
硬件:根据目标并发量调整,一般4C 8G的单台Slave可以支撑2000~5000并发的HTTP脚本。
2. 软件要求,所有机器必须一致
JDK:推荐OpenJDK 11 或 17,JMeter 5.6要求JDK 8+。
JMeter:去官网下载相同版本的二进制包(如apache-jmeter-5.6.3.tgz),不要用不同版本混用。
三、安装JDK和JMeter
以下以 Linux 为例,Windows 可参考同样思路。
1. 安装JDK
bash
# 以 Ubuntu 为例,安装 OpenJDK 17
sudo apt update
sudo apt install openjdk-17-jdk -y
# 版本
java -version
2. 安装 JMeter
bash
# 在每台机器上执行
cd /opt
sudo wget https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.tgz
sudo tar -xzf apache-jmeter-5.6.3.tgz
sudo mv apache-jmeter-5.6.3 jmeter
# 配置环境变量(可选,方便使用)
echo 'export JMETER_HOME=/opt/jmeter' >> ~/.bashrc
echo 'export PATH=$JMETER_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
安装完成后,在任意目录执行 jmeter -v 能显示版本信息即成功。
四、配置Slave负载机
在每台Slave机器上操作。假设有三台Slave,IP 分别为192.168.1.20、192.168.1.30、192.168.1.40。
1. 修改 jmeter.properties
编辑 $JMETER_HOME/bin/jmeter.properties,找到并修改以下项:
properties
# 开启远程分布式方式(默认就是这个值,保证未被注释)
server_port=1099
# 关闭 RMI 的 SSL,避免证书麻烦(测试内网环境建议关闭)
server.rmi.ssl.disable=true
# 指定 RMI 本地端口(可选,避免随机端口被防火墙拦截)
server.rmi.localport=50000
1099是Master和Slave通信的控制端口,50000为返回数据的本地端口,可按需修改。
2. 指定Slave的RMI主机名
如果Slave有多网卡、云服务器有公私网IP,必须显式设置RMI暴露的 IP。
编辑Slave的 jmeter-server 启动脚本:
Linux 下编辑 $JMETER_HOME/bin/jmeter-server
bash
# 在文件前面的注释之后、启动命令之前,添加:
JVM_ARGS="-Djava.rmi.server.hostname=192.168.1.20 $JVM_ARGS"
将192.168.1.20 替换为该Slave的真实内网IP。
如果找不到合适位置,直接在最后一行 exec "$PRGDIR/jmeter" ... 前加入 JVM_ARGS="..." 再导出即可。
更简单方法直接以命令行方式启动时传入参数:
bash
./jmeter-server -Djava.rmi.server.hostname=192.168.1.20
推荐直接修改脚本,一劳永逸。
Windows 下编辑 jmeter-server.bat
在文件开头附近加入:
bat
set JVM_ARGS=-Djava.rmi.server.hostname=192.168.1.20 %JVM_ARGS%
3. 启动 Slave 服务
bash
cd /opt/jmeter/bin
./jmeter-server
如果看到类似以下日志,说明启动成功:
text
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[192.168.1.20:50000] ...]]
Starting the test on host 192.168.1.20
默认前台运行,测试时可先这样;生产建议配合 nohup 或 systemd 做成后台服务:
bash
nohup ./jmeter-server > jmeter-server.log 2>&1 &
注意防火墙必须放通控制端口 1099 和数据端口 50000,如果是云服务器要去安全组添加入方向规则,TCP协议,源为Master机器 IP。
五、配置Master控制机
假设 Master IP 为 192.168.1.10。
1. 修改 jmeter.properties
编辑 $JMETER_HOME/bin/jmeter.properties:
properties
# 关闭 RMI SSL
server.rmi.ssl.disable=true
# 指定远程 Slave 列表,格式:IP:端口,多个逗号分隔
remote_hosts=192.168.1.20:1099,192.168.1.30:1099,192.168.1.40:1099
# Master 本身是不是作为负载机执行测试,默认 false 表示不执行,改为 true 会同时作为负载机
# 一般保持 false,让 Master 只负责调度和收集结果
master.use.localHost=false
保存后退出。
2. 测试Slave连通性
在 Master 上执行:
bash
# 检查 JMeter 是不是识别远程主机
jmeter -n -t examples/CSVSample.jmx -r -l test.jtl -Jremote_hosts="192.168.1.20:1099"
或者 GUI方式快速测试。
六、执行分布式压力测试
方式 1:GUI方式用于调试
在Master上启动 JMeter GUI:
bash
jmeter
打开或新建一个测试计划(如添加线程组、HTTP 请求)。
在菜单栏点击远程启动:
远程启动所有:启动 remote_hosts 里所有Slave。
远程启动可选择单个Slave:单独启动某一台调试。
观察Slave窗口日志,GUI 的查看结果树、聚合报告等监听器将显示汇总结果。
方式 2:命令行非GUI 方式
方式节省资源,结果更稳定。
bash
jmeter -n -t /path/to/testplan.jmx \
-r \ # 启动 remote_hosts 中定义的所有 Slave
-l /path/to/result.jtl \
-e -o /path/to/report # 测试结束后自动生成 HTML 报告
参数说明:
-n:非 GUI 方式
-t:指定测试计划文件
-r:启动 remote_hosts 里所有远程 Slave
-R:手动指定 Slave 列表,如 -R 192.168.1.20:1099,192.168.1.30:1099
-l:保存采样结果的 JTL 文件
-e -o:在测试结束后立即生成 HTML 报告到指定目录
示例:
bash
jmeter -n -t /home/user/MyTest.jmx -r -l /home/user/result.jtl -e -o /home/user/report
七、注意事项和问题
1. 参数化 CSV 文件分发
JMeter 分布式不会自动同步测试用的外部文件(CSV、properties 等)。
需要:
手动将 CSV 文件复制到每台 Slave 相同的绝对途径下(如 /data/test/users.csv)。
或使用相对途径,并将文件放在 Slave 的 $JMETER_HOME/bin 下,但强烈建议用绝对途径。
如果使用 Redis、数据库等作为数据源,则无此问题。
2. 版本必须完全一致
Master 和所有 Slave 的 JMeter 大版本(如 5.6.3)及 JDK 版本最好相同,否则可能出现序列化错误。
3. 连接被拒绝出现Connection refused
检查 Slave 的 jmeter-server 是不是启动。
检查 java.rmi.server.hostname 是不是设置为 Master 可达的 IP(不能是 127.0.0.1)。
检查防火墙/安全组是不是放通 1099 和 50000 端口。
4. 内存溢出OOM
在 Slave 上,按需调整 JVM 堆大小,编辑 jmeter-server 或 jmeter 脚本中的:
bash
HEAP="-Xms1g -Xmx4g -XX:MaxMetaspaceSize=256m"
根据机器内存适当加大 -Xmx。
5. Slave 找不到测试计划
使用命令行方式时,测试计划是由 Master 通过 RMI 发送给 Slave 的,不需要在 Slave 上存放 .jmx 文件。只有外部依赖文件需要手动放置。
6. 多网卡或云主机绑定 IP
云服务器内网 IP 往往不是公网 IP,但Master和Slave都在内网时,将 java.rmi.server.hostname 设为内网IP即可。如果跨公网(不推荐),需使用公网 IP 并配置相应的端口映射和SSL。
八、使用systemd托管Slave(CentOS/Ubuntu 通用)
创建文件 /etc/systemd/system/jmeter-slave.service:
ini
[Unit]
Description=JMeter Slave Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/jmeter/bin
Environment="JVM_ARGS=-Djava.rmi.server.hostname=192.168.1.20"
ExecStart=/opt/jmeter/bin/jmeter-server
Restart=on-failure
[Install]
WantedBy=multi-user.target
然后执行:
bash
systemctl daemon-reload
systemctl start jmeter-slave
systemctl enable jmeter-slave
九、流程总结
搭建流程:
统一安装 JDK + JMeter
配置 Slave(关闭 SSL,指定 hostname,启动 jmeter-server)
配置 Master(指定 remote_hosts,关闭 SSL)
准备外部测试数据到 Slave
在 Master 上用命令行发动分布式测试
这样一套 JMeter 分布式环境就搞定了,可以根据被测系统的承载能力水平扩展 Slave 机器,轻松发起数十万甚至百万并发的压力。