—
前言
大家好,我是运维与测试,做过多年性能测试。JMeter是我最常用的压测工具,但在处理高并发场景时,单机JMeter往往扛不住压力。今天这篇文章,分享JMeter分布式压测的实战经验。
—
一、为什么需要分布式压测?
单机瓶颈
JMeter单机运行时,瓶颈在于:
- CPU:JMeter是Java应用,模拟大量用户需要CPU资源
- 内存:每个线程消耗内存,线程数越多内存占用越大
- 网络:单机网卡带宽有限
实测数据:
| 并发数 | 单机JMeter表现 |
|---|---|
| 100 | 稳定 |
| 500 | CPU 70%+ |
| 1000 | CPU 95%+,响应时间变长 |
| 2000+ | JMeter崩溃或报错 |
分布式压测方案
分布式压测使用多台机器:
- Controller:控制节点,调度测试
- Agent/Server:执行节点,实际产生压力
架构:
Controller (控制节点)
└── Agent1 (执行节点)
└── Agent2 (执行节点)
└── Agent3 (执行节点)
└── …
—
二、JMeter分布式部署
环境准备
Controller节点:
- JMeter安装
- JDK环境
- 足够内存(建议4G+)
Agent节点:
- JMeter安装
- JDK环境
- jmeter-server启动
配置Agent节点
1. 编辑jmeter.properties
properties
Agent配置文件
remote_hosts=192.168.1.101:1099,192.168.1.102:1099,192.168.1.103:1099
server_port=1099
server.rmi.localport=1099
2. 启动Agent服务
bash
Linux/Mac
./jmeter-server
Windows
jmeter-server.bat
配置Controller节点
properties
Controller的jmeter.properties
remote_hosts=192.168.1.101,192.168.1.102,192.168.1.103
server.rmi.ssl.disable=true # 关闭SSL(内网测试)
启动分布式测试
方式1:GUI模式
在JMeter GUI中:
- 点击
Run–
Remote Start All - 或选择单个Agent启动
方式2:命令行模式
bash
启动所有Agent
jmeter -n -t test.jmx -r
启动指定Agent
jmeter -n -t test.jmx -R 192.168.1.101,192.168.1.102
—
三、分布式压测实战
测试脚本设计
关键点:分布式脚本要考虑线程分配
xml
100
10
true
300
注意:
- 每个Agent都会执行完整脚本
- 100线程 × 3个Agent = 300实际并发
- 线程数要按Agent数量分配
测试数据分离
分布式测试的数据问题:
- 每个Agent使用相同数据文件
- 可能产生数据重复
解决方案:CSV数据文件分割
Agent1: data_1.csv
Agent2: data_2.csv
Agent3: data_3.csv
在脚本中使用变量:
${__P(data.file,data_${agent_id}.csv)}
测试报告合并
JMeter 5.0+支持分布式报告自动合并:
bash
生成HTML报告
jmeter -n -t test.jmx -r -l result.jtl -e -o report_folder
—
四、性能优化技巧
JMeter优化配置
properties
jmeter.properties优化
增加内存
HEAP=-Xms4g -Xmx4g
使用G1垃圾回收
GC_ALGO=-XX:+UseG1GC -XX:MaxGCPauseMillis=100
关用GUI优化
jmeter.save.saveservice.output_format=csv
jmeter.save.saveservice.data_type=true
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
jmeter.save.saveservice.response_data=false # 不保存响应体
jmeter.save.saveservice.response_message=true
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.subresults=false
jmeter.save.saveservice.assertions=true
jmeter.save.saveservice.latency=true
jmeter.save.saveservice.connect_time=true
jmeter.save.saveservice.samplerData=false
jmeter.save.saveservice.responseHeaders=false
jmeter.save.saveservice.requestHeaders=false
jmeter.save.saveservice.encoding=false
jmeter.save.saveservice.bytes=true
jmeter.save.saveservice.sent_bytes=true
jmeter.save.saveservice.url=true
禁用监听器
测试执行时禁用所有监听器:
- View Results Tree
- Aggregate Report
- Summary Report
使用后端监听器替代:
xml
org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient
org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender
http://influxdb:8086/write?db=jmeter
使用非GUI模式
bash
性能对比
GUI模式:CPU占用高,响应慢
非GUI模式:CPU占用低,响应快
推荐命令
jmeter -n -t test.jmx -l result.jtl -Jthreads=100 -Jrampup=10 -Jduration=300
—
五、监控与报告
InfluxDB + Grafana监控
1. 安装InfluxDB
bash
docker run -d -p 8086:8086 influxdb:2.0
2. 创建数据库
sql
CREATE DATABASE jmeter
3. JMeter配置Backend Listener
xml
http://localhost:8086/write?db=jmeter
jmeter_results
4. Grafana配置
导入JMeter Dashboard模板(ID: 5495)
关键监控指标
| 指标 | 说明 | 告警阈值 |
|---|---|---|
| 平均响应时间 | 请求平均耗时 |
|
| 最大响应时间 | 最慢请求耗时 |
3000ms |
| TPS | 每秒事务数 | 1% |
| CPU使用率 | Agent节点CPU |
80% |
| 内存使用率 | Agent节点内存 |
85% |
—
六、常见问题解决
问题1:Agent连接失败
错误:
Connection refused to host: 192.168.1.101
解决:
bash
检查防火墙
firewall-cmd –add-port=1099/tcp –permanent
firewall-cmd –add-port=50000/tcp –permanent
firewall-cmd –reload
或临时关闭防火墙
systemctl stop firewalld
问题2:Agent启动报错
错误:
Error creating rmi server
解决:
bash
编辑启动脚本
jmeter-server.sh
SERVER_RMI_HOST=-Djava.rmi.server.hostname=192.168.1.101
或在jmeter.properties中设置
server.rmi.host=192.168.1.101
问题3:报告数据不准
原因:Agent时钟不同步
解决:
bash
同步所有节点时间
ntpdate time.windows.com
或使用chrony
systemctl start chronyd
—
七、实战案例:电商系统压测
测试场景
电商大促场景:
- 用户登录:10%流量
- 商品浏览:60%流量
- 下单支付:30%流量
压测配置
yaml
目标并发: 10000 TPS
Agent节点: 10台
每台线程: 1000
压测时长: 1小时
预热时间: 5分钟
测试脚本结构
ThreadGroup (1000线程)
├── If Controller (10%) –
登录场景
├── If Controller (60%) –
商品浏览场景
└── If Controller (30%) –
下单支付场景
压测结果分析
| 指标 | 结果 | 结论 |
|---|---|---|
| TPS | 8500 | 未达标,需优化 |
| 平均响应时间 | 350ms | 正常 |
| 错误率 | 0.5% | 正常 |
| 系统CPU | 75% | 有余量 |
| 数据库CPU | 95% | 瓶颈点 |
优化建议:
- 数据库增加连接池
- 添加Redis缓存
- SQL查询优化
—
八、RunnerGo对比
RunnerGo内置性能测试功能,相比JMeter:
| 对比项 | JMeter | RunnerGo |
|---|---|---|
| 分布式支持 | 需手动配置 | 内置支持 |
| 监控集成 | 需额外配置 | 内置监控 |
| 报告可视化 | Grafana集成 | 内置报告 |
| 学习难度 | 较高 | 较低 |
| 可视化编排 | XML脚本 | 可视化 |
如果团队不熟悉JMeter,RunnerGo是更好的选择。
—
总结
JMeter分布式压测要点:
| 环节 | 关键配置 |
|---|---|
| Agent部署 | jmeter-server启动 |
| Controller配置 | remote_hosts配置 |
| 脚本设计 | 线程数按Agent分配 |
| 数据分离 | CSV文件分割 |
| 监控集成 | InfluxDB+Grafana |
| 性能优化 | 非GUI、禁用监听器 |
—
下期预告:RestAssured框架精讲 – Java接口自动化测试从0到1