JMeter工作原理

测试环境搭建
bash
# 下载JMeter
wget https://dlcdn.apache.org/jmeter/binaries/apache-jmeter-5.6.2.tgz
tar -xzf apache-jmeter-5.6.2.tgz
cd apache-jmeter-5.6.2/bin
./jmeter.sh # Linux/Mac
# 或 jmeter.bat # Windows
创建基础HTTP负载测试

线程组配置
bash
线程数: 100 # 并发用户数
Ramp-Up时间: 60 # 在60秒内启动所有用户
循环次数: 永远 # 持续运行
调度器: 启用,持续时间300秒 # 测试运行5分钟
分布式负载测试
bash
# 控制机配置
remote_hosts=192.168.1.101,192.168.1.102,192.168.1.103
# 启动从机
jmeter-server -Dserver_port=1099
# 从控制机执行分布式测试
jmeter -n -t testplan.jmx -R 192.168.1.101,192.168.1.102 -l results.jtl
复杂业务场景模拟
java
// 使用JSR223采样器实现复杂逻辑
import org.apache.jmeter.protocol.http.control.Header
// 动态生成请求参数
def timestamp = System.currentTimeMillis()
def signature = org.apache.commons.codec.digest.DigestUtils.md5Hex("data${timestamp}")
vars.put("timestamp", timestamp.toString())
vars.put("signature", signature)
// 设置动态请求头
sampler.getHeaderManager().add(new Header("X-Signature", signature))

关键性能指标
java
吞吐量(Throughput): 系统每秒处理请求数
响应时间(Response Time):
- 平均值(Average)
- 中位数(Median)
- 90%百分位(90% Line)
错误率(Error Rate): 失败请求百分比
并发用户数(Active Threads): 实时并发用户数量
实时监控配置
XML
<!-- 添加后端监听器进行实时监控 -->
<BackendListener guiclass="BackendListenerGui" testclass="BackendListener" testname="InfluxDB Backend Listener">
<elementProp name="arguments" elementType="Arguments">
<collectionProp name="Arguments.arguments">
<elementProp name="influxdbMetricsSender" elementType="Argument">
<stringProp name="Argument.name">influxdbMetricsSender</stringProp>
<stringProp name="Argument.value">org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender</stringProp>
</elementProp>
<elementProp name="influxdbUrl" elementType="Argument">
<stringProp name="Argument.name">influxdbUrl</stringProp>
<stringProp name="Argument.value">http://localhost:8086/write?db=jmeter</stringProp>
</elementProp>
</collectionProp>
</elementProp>
</BackendListener>
网站负载测试示例
XML
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.2">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="电商网站负载测试" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="base_url" elementType="Argument">
<stringProp name="Argument.name">base_url</stringProp>
<stringProp name="Argument.value">https://api.ecommerce.com</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
</TestPlan>
<hashTree>
<!-- 线程组:浏览商品 -->
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="浏览商品用户" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">10</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">50</stringProp>
<stringProp name="ThreadGroup.ramp_time">30</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">300</stringProp>
<stringProp name="ThreadGroup.delay">0</stringProp>
</ThreadGroup>
<hashTree>
<!-- HTTP请求默认值 -->
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">${base_url}</stringProp>
<stringProp name="HTTPSampler.port">443</stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path"></stringProp>
<stringProp name="HTTPSampler.concurrentPool">6</stringProp>
<stringProp name="HTTPSampler.connect_timeout">5000</stringProp>
<stringProp name="HTTPSampler.response_timeout">10000</stringProp>
</ConfigTestElement>
<hashTree/>
<!-- 浏览商品列表 -->
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="获取商品列表" enabled="true">
<boolProp name="HTTPSampler.postBodyRaw">false</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">${base_url}</stringProp>
<stringProp name="HTTPSampler.port">443</stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/api/v1/products</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<stringProp name="HTTPSampler.follow_redirects">true</stringProp>
<stringProp name="HTTPSampler.auto_redirects">false</stringProp>
<stringProp name="HTTPSampler.use_keepalive">true</stringProp>
<stringProp name="HTTPSampler.DO_MULTIPART_POST">false</stringProp>
<stringProp name="HTTPSampler.concurrentPool">6</stringProp>
<stringProp name="HTTPSampler.connect_timeout">5000</stringProp>
<stringProp name="HTTPSampler.response_timeout">10000</stringProp>
</HTTPSamplerProxy>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
使用BeanShell进行动态参数处理
java
// BeanShell预处理程序 - 动态签名生成
import java.security.MessageDigest;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
// 获取当前时间戳
long timestamp = System.currentTimeMillis();
vars.put("timestamp", String.valueOf(timestamp));
// 生成随机用户ID
int randomUserId = (int)(Math.random() * 10000) + 1;
vars.put("user_id", String.valueOf(randomUserId));
// 生成API签名
String secretKey = "your_secret_key";
String dataToSign = timestamp + ":" + randomUserId;
String signature = generateSignature(dataToSign, secretKey);
vars.put("signature", signature);
String generateSignature(String data, String key) {
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] bytes = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(bytes);
} catch (Exception e) {
return "error";
}
}
生成HTML报告
bash
# 生成详细的HTML报告
jmeter -n -t testplan.jmx -l results.jtl -e -o /path/to/report/output
# 报告包含内容:
# - 仪表板概览
# - 统计表格
# - 错误分析
# - 响应时间分布
# - 随时间变化图表
自定义报告模板
XML
<!-- 自定义报告生成配置 -->
<jmeterReport>
<reportConfig>
<title>性能测试报告</title>
<dateFormat>yyyy-MM-dd HH:mm:ss</dateFormat>
<pdfExport>true</pdfExport>
<charts>
<responseTime>true</responseTime>
<throughput>true</throughput>
<hitsPerSecond>true</hitsPerSecond>
<responseTimePercentiles>true</responseTimePercentiles>
</charts>
</reportConfig>
</jmeterReport>
第一阶段: 基准测试 - 单用户验证功能
第二阶段: 负载测试 - 逐步增加并发用户
第三阶段: 压力测试 - 达到系统极限
第四阶段: 耐力测试 - 长时间稳定运行
第五阶段: 尖峰测试 - 突发流量测试