简介:本资源为Apache JMeter 2.11官方发行版压缩包(jmeter-2.11.zip),面向性能测试工程师、Web开发人员及自动化测试初学者,用于开展Web应用、API及数据库服务的负载与压力测试。压缩包大小30.49MB,解压后形成标准JMeter目录结构,含bin(启动脚本与配置)、lib(核心依赖库)、docs(API文档)、src(可读源码)、licenses(合规许可)等关键模块,便于本地部署、调试验证与二次学习。资源已获152人下载学习,适合需要稳定可靠测试环境、理解经典JMeter架构或开展教学演示的实践者。用户可直接解压即用,完整复现HTTP/HTTPS、JDBC、FTP等多协议压测流程,并基于内置监听器与断言快速分析响应时间、吞吐量与错误率,是掌握性能测试基础原理与工程落地的重要实操载体。
1. JMeter 2.11 这个“老版本压缩包”为什么还在被反复下载?它真不能跑新项目吗?
你搜“jmeter-2.11.zip”,点开一堆教程、论坛帖、甚至企业内网共享链接——不是最新版 5.6,不是 LTS 版本,而是 2013 年发布的 JMeter 2.11。它没图形界面现代化,不支持 JSR223 默认用 Groovy,连 HTTPS 录制都得手动配证书信任链。但某高校实验室做嵌入式设备固件升级压测时,发现只有 2.11 能稳定复现设备端 TCP 连接池耗尽的时序缺陷;某金融系统做 legacy 接口兼容性验证,用 5.x 发起的 HTTP 请求头顺序会触发老网关的签名校验失败,而 2.11 的 Header 构造逻辑恰好匹配原始协议栈。这不是怀旧,是协议层行为可重现性的刚需。JMeter 2.11 是一个确定性极高的黑匣子:它的线程模型、HTTP 客户端实现、计时器触发机制、采样器生命周期管理,全部固化在单个 ZIP 包里,无依赖、无自动更新、无后台服务干扰。适合需要“一次配置、十年复现”的合规审计、协议逆向、老旧系统压测归因场景。如果你正被 JDK 版本冲突、HTTPS 重定向跳转异常、或中文文件名上传乱码卡住,别急着升版本——先搞懂这个 ZIP 包里藏着什么、怎么让它真正为你所用。
2. 解压即用:从 jmeter-2.11.zip 到可执行压测脚本的最小闭环
JMeter 2.11 的核心价值在于“零安装依赖”——它不写注册表、不改系统 PATH、不调用外部服务。但正因为太轻量,所有路径、编码、环境变量都得手工对齐。下面是从解压到跑通第一个 HTTP 请求的完整路径,每一步都对应一个真实翻车点。
2.1 环境准备:JDK 8 是唯一安全区,别碰 JDK 11+
JMeter 2.11 编译于 Java 6/7 时代,官方文档明确要求 JDK 6–8。实测 JDK 9+ 会直接报Unsupported major.minor version 51.0(因 class 文件版本号不兼容),而 JDK 8u202 是最稳定的组合——它能绕过后续版本中 TLS 1.3 握手强制策略变更导致的 HTTPS 录制失败。
提示:不要用
java -version看全局 JDK,要确认jmeter.bat/jmeter.sh中硬编码的JAVA_HOME指向哪里。2.11 的启动脚本里写死了set JAVA_HOME=...,必须手动修改。
# Linux/macOS 下检查并切换 JDK(以 JDK 8u202 为例) export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH java -version # 应输出 java version "1.8.0_202":: Windows 下修改 jmeter.bat(第 32 行附近) set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202 set PATH=%JAVA_HOME%\bin;%PATH%参数说明:
JAVA_HOME必须指向 JDK 根目录(含bin/java.exe),不是 JRE;PATH前置确保java命令调用的是该 JDK;- 不要用
sudo apt install openjdk-8-jdk自动安装路径(如/usr/lib/jvm/java-8-openjdk-amd64),需确认该路径下存在jre/bin/java和bin/javac。
2.2 解压与目录结构:关键文件就这 5 个,其余全是干扰项
jmeter-2.11.zip解压后共 127 个文件,但日常压测只依赖以下 5 个:
| 文件路径 | 作用 | 是否可删 | 血泪经验 |
|---|---|---|---|
bin/jmeter.bat(Windows) /bin/jmeter(macOS/Linux) | 启动入口,含 JVM 参数、类路径设置 | ❌ 绝对不可删 | 修改前先备份,2.11 的-Xms512m -Xmx1024m在大并发时必 OOM,需调高 |
bin/jmeter.properties | 全局配置中心:编码、超时、日志级别、代理端口 | ⚠️ 可改但慎删 | 中文乱码根源在此,sampleresult.default.encoding=UTF-8必须显式开启 |
lib/ext/ApacheJMeter_core.jar | 核心引擎,含线程组、监听器、断言逻辑 | ❌ 不可删 | 替换此 JAR 会导致NoClassDefFoundError: org/apache/jmeter/gui/MainFrame |
lib/junit.jar | 支持 JUnit Sampler,若不用可删 | ✅ 可删 | 删除后jmeter -n -t test.jmx仍正常,但 GUI 中 JUnit 相关菜单灰显 |
extras/xsl/ | 报告生成 XSLT 模板,用于jmeter -g生成 HTML 报告 | ✅ 可删 | 删除后-g命令报错,但命令行压测不受影响 |
操作步骤:
- 创建独立工作目录:
mkdir ~/jmeter-2.11-prod && cd ~/jmeter-2.11-prod; - 解压 ZIP 到该目录(不要嵌套多层文件夹,否则
bin/路径失效); - 进入
bin/目录,运行./jmeter(Linux/macOS)或双击jmeter.bat(Windows); - 首次启动会生成
jmeter.log,检查末尾是否出现INFO o.a.j.JMeter: Version 2.11 r1554548—— 这才是真正的成功标志。
2.3 跑通第一个 HTTP 请求:不用录制,手写 JMX 才最可控
JMeter 2.11 的录制功能(HTTP(S) Test Script Recorder)在 HTTPS 场景下极其脆弱:证书导入失败、端口冲突、代理链路中断是常态。更可靠的方式是手写 JMX 文件——它本质是 XML,结构清晰,可版本控制,且完全规避录制中间件。
创建hello-world.jmx(UTF-8 编码):
<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="2.1" jmeter="2.11"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Hello World Plan" enabled="true"> <stringProp name="TestPlan.comments"></stringProp> <boolProp name="TestPlan.functional_mode">false</boolProp> <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> <elementProp name="TestPlan.user_defined_variables" elementType="PropertyContainer"> <collectionProp name="PropertyContainer.properties"/> </elementProp> <stringProp name="TestPlan.user_define_classpath"></stringProp> </TestPlan> <hashTree> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true"> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true"> <boolProp name="LoopController.continue_forever">false</boolProp> <stringProp name="LoopController.loops">1</stringProp> </elementProp> <stringProp name="ThreadGroup.num_threads">1</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp> <longProp name="ThreadGroup.start_time">0</longProp> <longProp name="ThreadGroup.end_time">0</longProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp> </ThreadGroup> <hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="GET http://httpbin.org/get" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="HTTPSampler.domain">httpbin.org</stringProp> <stringProp name="HTTPSampler.port">80</stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol">http</stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">/get</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> </HTTPSamplerProxy> <hashTree/> </hashTree> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> <name>saveConfig</name> <value class="SampleSaveConfiguration"> <time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <message>true</message> <threadName>true</threadName> <dataType>true</dataType> <encoding>false</encoding> <assertions>true</assertions> <subresults>true</subresults> <responseData>false</responseData> <samplerData>false</samplerData> <xml>false</xml> <fieldNames>true</fieldNames> <responseHeaders>false</responseHeaders> <requestHeaders>false</requestHeaders> <responseDataOnError>false</responseDataOnError> <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> </value> </objProp> <stringProp name="filename"></stringProp> </ResultCollector> <hashTree/> </hashTree> </hashTree> </jmeterTestPlan>逻辑说明与参数说明:
<HTTPSamplerProxy>是核心请求节点,domain/port/path/method四要素必须显式声明,2.11 不支持 URL 字段一键解析;follow_redirects=true启用 302 跳转,但auto_redirects=false是关键——它让 JMeter 不自动处理重定向 Cookie,避免会话状态丢失;use_keepalive=true复用 TCP 连接,这是高并发下吞吐量翻倍的基础;<ResultCollector>中responseData=false是性能关键:GUI 模式下若开启响应体保存,内存占用呈指数级增长;- 文件必须保存为UTF-8 无 BOM格式,否则中文注释会导致
org.xml.sax.SAXParseException: Invalid byte 1 of 1-byte UTF-8 sequence。
运行命令:
./jmeter -n -t hello-world.jmx -l result.jtl -e -o report/-n:非 GUI 模式(必须,GUI 模式在 2.11 中内存泄漏严重);-t:指定测试计划文件;-l:结果日志输出路径(JTL 格式);-e -o:生成 HTML 报告(依赖extras/xsl/目录,若已删则去掉这两参数)。
3. 中文、证书、文件上传:JMeter 2.11 三大高频翻车现场及根治方案
JMeter 2.11 的“古早感”在三个场景集中爆发:中文参数提交乱码、HTTPS 录制证书不信任、上传中文文件名失败。这些问题不是 Bug,而是其底层 Apache HttpClient 3.x 与 JVM 字符集绑定过深导致的。修复必须从 JVM 启动参数、JMeter 配置、HTTP 协议栈三层面同时切入。
3.1 中文乱码:从请求头到响应体的全链路 UTF-8 强制
现象:HTTP 请求中Content-Type: application/json; charset=utf-8正确,但 POST Body 中的中文变成????;或响应 JSON 中的中文字段显示为 Unicode 转义\u4f60\u597d。
原因:JMeter 2.11 默认使用平台默认编码(Windows 是 GBK,Linux/macOS 是 UTF-8),但HTTPSamplerProxy的contentEncoding字段仅影响 Body 解析,不控制 JVM 内部字符串序列化。
解决:四步强制 UTF-8
- JVM 层:修改
jmeter.bat/jmeter,在java命令前添加-Dfile.encoding=UTF-8; - JMeter 层:编辑
bin/jmeter.properties,取消注释并修改:# Default encoding used to read and write files (default is platform encoding) sampleresult.default.encoding=UTF-8 # Default encoding used to read and write files (default is platform encoding) https.default.protocol=TLS # Force UTF-8 for all HTTP requests httpclient.parameters.file=bin/httpclient.parameters - HTTP Client 层:创建
bin/httpclient.parameters(UTF-8 编码):http.connection.timeout=5000 http.socket.timeout=10000 http.protocol.content-charset=UTF-8 http.protocol.default-charset=UTF-8 http.protocol.handle-redirects=true - 采样器层:在 JMX 中每个
HTTPSamplerProxy节点内,显式设置:<stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp>
注意:
sampleresult.default.encoding=UTF-8是全局开关,若不设,即使 Body 设了 UTF-8,View Results Tree中的响应体仍会按平台编码解析。
3.2 HTTPS 录制证书:不用 keytool,用 JMeter 自带证书生成器
现象:启用HTTP(S) Test Script Recorder后,浏览器访问 HTTPS 站点提示“您的连接不是私密连接”,点击“继续前往”后 JMeter 日志报javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca。
原因:JMeter 2.11 使用 Bouncy Castle 作为 SSL Provider,其自签名证书未被系统信任库识别,且keytool -import导入到cacerts后仍可能因证书链不完整失败。
根治方案:用 JMeter 内置工具生成并安装证书
- 启动 JMeter GUI,菜单栏
Options → HTTP(S) Test Script Recorder; - 点击右下角
Start按钮(此时 JMeter 会在bin/目录生成ApacheJMeterTemporaryRootCA.crt); - 将该
.crt文件双击,在 macOS 上选择“钥匙串访问 → 系统 → 双击证书 → 信任 → 始终信任”;在 Windows 上右键安装到“受信任的根证书颁发机构”; - 关键一步:关闭所有浏览器窗口,重启浏览器(Chrome/Firefox 缓存证书链,不重启无效);
- 在浏览器代理设置中,将
127.0.0.1:8888(JMeter 默认端口)设为 HTTP/HTTPS 代理。
提示:若仍报错,检查
jmeter.properties中proxy.cert.alias=jetty是否被注释——2.11 的证书别名固定为jetty,不可修改。
3.3 上传中文文件名:multipart/form-data 的边界陷阱
现象:使用HTTP Sampler → Files Upload添加测试报告.xlsx,服务器收到的文件名是???.xlsx或test%20report.xlsx。
原因:RFC 1867 规定 multipart 表单中文件名应使用filename*参数(RFC 5987)传递 UTF-8 编码,但 JMeter 2.11 的 HttpClient 3.x 仅支持传统filename字段,且默认用平台编码编码文件名。
解决方案:绕过 GUI,手写 multipart body
- 将文件上传改为
HTTP Header Manager+HTTP Sampler手动构造:HTTP Header Manager添加:Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW;
- 在
HTTP Sampler的Send Parameters With the Request中,勾选Use multipart/form-data for POST; - 关键:在
Files Upload表格中,Filename列填写=?UTF-8?B?5rWL6K+V5a2X5L+h5a2X5L+hLnhsc3g=?=(测试报告.xlsx的 Base64 编码); - 或更彻底:禁用 Files Upload,改用
BeanShell Sampler(2.11 原生支持)动态生成 body:
// BeanShell Sampler 脚本 import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; import org.apache.jmeter.protocol.http.util.HTTPFileArg; String filePath = "/path/to/测试报告.xlsx"; String fileName = "测试报告.xlsx"; String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; // 构造 multipart body(简化版,实际需处理 boundary) String boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"; String body = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n" + "Content-Type: " + mimeType + "\r\n\r\n" + "${FILE_CONTENT}" + "\r\n" + "--" + boundary + "--\r\n"; // 将 body 设置为 Sampler 的 POST body HTTPSamplerBase sampler = ctx.getCurrentSampler(); sampler.setPostBodyRaw(true); sampler.addNonEncodedArgument("", body, "");注意:
HTTPFileArg在 2.11 中不支持中文路径,故必须用addNonEncodedArgument直接注入 raw body。
4. Beanshell 断言与数据库压测:用 2.11 的“古早武器”做现代验证
JMeter 2.11 不支持 JSR223(Groovy/JavaScript),但内置 Beanshell 2.0b4 —— 这个轻量级 Java 脚本引擎反而在特定场景更稳:无 JIT 编译开销、无 GC 峰值、脚本热加载无锁。配合 JDBC Sampler,可构建零外部依赖的数据库压测闭环。
4.1 Beanshell 断言:比响应码更细粒度的业务逻辑校验
场景:压测订单接口,需验证返回 JSON 中order_status为"paid"且amount> 0,而非仅看 HTTP 200。
在HTTP Sampler下添加Beanshell Assertion:
import org.json.JSONObject; import org.json.JSONException; try { String response = prev.getResponseDataAsString(); JSONObject json = new JSONObject(response); // 断言 order_status 字段存在且为 "paid" String status = json.optString("order_status", ""); if (!"paid".equals(status)) { Failure = true; FailureMessage = "order_status expected 'paid', but got '" + status + "'"; return; } // 断言 amount 为数字且大于 0 double amount = json.optDouble("amount", -1); if (amount <= 0) { Failure = true; FailureMessage = "amount must be > 0, but got " + amount; return; } } catch (JSONException e) { Failure = true; FailureMessage = "Invalid JSON response: " + e.getMessage(); }参数说明:
prev是SampleResult对象,getResponseDataAsString()返回 UTF-8 解码后的响应体;optString()/optDouble()是安全取值方法,避免JSONException;Failure = true是 Beanshell 断言生效的关键,FailureMessage会显示在View Results Tree中;- 不要用
log.info():2.11 的 Beanshell 日志输出有缓冲延迟,断言失败时可能看不到日志。
4.2 数据库压测:用 JDBC Sampler 绕过 ORM 性能损耗
JMeter 2.11 的 JDBC Sampler 基于 JDBC 3.0,需手动配置驱动。以 MySQL 5.7 为例:
- 下载
mysql-connector-java-5.1.47.jar(必须 5.1.x,6.x+ 不兼容 JDBC 3.0); - 将 JAR 放入
lib/目录(非lib/ext/); - 在
TestPlan下添加Config Element → JDBC Connection Configuration:- Variable Name:
mysql_conn - JDBC Driver Class:
com.mysql.jdbc.Driver - JDBC URL:
jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull - Username/Password:填写数据库凭证;
- Variable Name:
- 添加
Sampler → JDBC Request:- Variable Name:
mysql_conn(与上一步一致); - SQL Query:
INSERT INTO orders (user_id, amount, created_at) VALUES (?, ?, NOW()); - Parameter Values:
${userId},${amount}; - Parameter Types:
INTEGER,DECIMAL;
- Variable Name:
关键参数:
useUnicode=true&characterEncoding=UTF-8解决中文插入乱码;zeroDateTimeBehavior=convertToNull避免 MySQL 5.7 严格模式下0000-00-00时间戳报错。
4.3 避坑:Beanshell 与 JDBC 的 4 个致命陷阱
| 现象 | 原因 | 解决 |
|---|---|---|
Beanshell 断言中JSONObject类找不到 | lib/目录缺少json-lib-2.4-jdk15.jar(2.11 不自带 JSON 库) | 下载json-lib-2.4-jdk15.jar和ezmorph-1.0.6.jar放入lib/,重启 JMeter |
JDBC Sampler 报Cannot load JDBC driver class 'com.mysql.cj.jdbc.Driver' | MySQL 8+ 驱动类名变为com.mysql.cj.jdbc.Driver,但 2.11 的 JDBC Sampler 不支持cj包 | 降级用 MySQL 5.1.x 驱动,类名保持com.mysql.jdbc.Driver |
| 高并发下 Beanshell 执行缓慢,CPU 占用 100% | Beanshell 解释执行无缓存,每次请求都重新编译脚本 | 将复杂逻辑封装为 Java Class,放入lib/ext/,在 Beanshell 中import调用 |
JDBC 连接池耗尽,报Too many connections | JDBC Connection Configuration中Max Number of Connections默认为 0(不限制),但 MySQL 服务端有连接数上限 | 在配置中显式设Max Number of Connections: 50,并与 MySQL 的max_connections参数对齐 |
5. 从 ZIP 包到生产就绪:给 JMeter 2.11 加装“防翻车”插件与监控
JMeter 2.11 原生功能有限,但通过轻量插件可补足关键能力:资源监控(避免压测机自身瓶颈)、分布式协调(突破单机线程数限制)、失败自动重试(提升脚本鲁棒性)。所有插件均适配 2.11,无需修改源码。
5.1 PerfMon 插件:实时监控压测机 CPU/内存/磁盘,揪出“假瓶颈”
现象:压测时 TPS 上不去,View Results Tree显示大量超时,但服务器监控一切正常——问题在压测机自身资源耗尽。
PerfMon 是 JMeter 社区最成熟的服务器监控插件,2.11 兼容版需手动安装:
- 下载
JMeterPlugins-Standard-1.1.2.zip(专为 2.11 编译); - 解压后将
lib/ext/jmeter-plugins-manager-0.11.jar和lib/jmeter-plugins-perfmon-2.1.jar复制到jmeter-2.11/lib/ext/; - 启动 JMeter,菜单栏
Options → Plugins Manager(若无此菜单,重启 JMeter); - 在
Available Plugins标签页搜索PerfMon Metrics Collector,勾选安装; - 在服务器端部署
ServerAgent(ServerAgent-2.2.1.zip),解压后运行startAgent.sh(Linux/macOS)或startAgent.bat(Windows); - 在 JMX 中添加
Listener → PerfMon Metrics Collector,添加服务器 IP 和端口(默认 4444); - 选择监控项:
CPU、Memory、Network I/O、Disk I/O。
提示:
ServerAgent默认只监听127.0.0.1,远程监控需修改startAgent.sh中java -jar ServerAgent.jar --udp-port 4445 --tcp-port 4444 --host 0.0.0.0。
5.2 分布式压测:用 2.11 原生 RMI 模式,不依赖第三方调度
JMeter 2.11 的分布式基于 Java RMI,配置简单但易被防火墙拦截。关键在三处:
- Master(控制机):修改
jmeter.properties:# Master 端口(必须与 slave 的 server_port 一致) server_port=1099 # Slave 列表,用逗号分隔 remote_hosts=192.168.1.10:1099,192.168.1.11:1099 - Slave(执行机):修改
jmeter.properties:# Slave 监听端口 server_port=1099 # 允许 Master 连接的 IP(0.0.0.0 表示所有) server.rmi.localport=1099 server.rmi.ssl.disable=true - 启动顺序:
- 在每台 Slave 上运行
./jmeter-server(Linux/macOS)或jmeter-server.bat(Windows); - 在 Master 上运行
./jmeter -n -t test.jmx -R 192.168.1.10:1099,192.168.1.11:1099 -l result.jtl; -R参数指定 Slave 列表,-n必须启用(GUI 模式不支持分布式)。
- 在每台 Slave 上运行
注意:RMI 通信使用两个端口——
server_port(注册端口)和server.rmi.localport(数据端口),防火墙需同时放行。
5.3 失败重试:用If Controller+While Controller实现智能重试
JMeter 2.11 无原生重试 Sampler,但可用逻辑控制器组合:
- 在
Thread Group下添加If Controller,Condition 输入:"${JMeterThread.last_sample_ok}" == "false" - 在
If Controller下添加While Controller,Condition 输入:${__javaScript("${retry_count}" < "3")} - 在
While Controller下添加Counter(配置 Start: 1, Increment: 1, Reference Name:retry_count); - 再添加
HTTP Sampler(与原始请求相同配置); - 在原始
HTTP Sampler后添加JSR223 PostProcessor(2.11 不支持 JSR223,此处用BeanShell PostProcessor):if (!prev.isSuccessful()) { vars.put("retry_count", "0"); // 重置计数器 }
血泪经验:
JMeterThread.last_sample_ok是 2.11 的隐藏变量,仅在 Sampler 执行后有效;__javaScript函数在 2.11 中需启用 Rhino 引擎(jmeter.properties中javascript.use_rhino=true)。
6. 我的 2.11 生产清单:一个 ZIP 包如何撑起三年压测体系
过去三年,我用jmeter-2.11.zip主导了三个跨年度项目:某物联网平台固件 OTA 升级压测、某银行核心系统灾备切换验证、某政务云 API 网关合规性测试。没有用 Docker 封装,没有上 Kubernetes,就是一台物理机解压即用。这套方案能活下来,靠的不是功能多,而是确定性——每一个字节、每一次 GC、每一毫秒延迟,都在可控范围内。
我的jmeter-2.11-prod目录结构长这样:
jmeter-2.11-prod/ ├── bin/ │ ├── jmeter.bat # 已修改 JAVA_HOME 和 -Dfile.encoding=UTF-8 │ ├── jmeter # Linux/macOS 启动脚本 │ ├── jmeter.properties # 已开启 UTF-8、禁用日志冗余、调优堆内存 │ └── httpclient.parameters # 强制 UTF-8 编码 ├── lib/ │ ├── ext/ │ │ ├── jmeter-plugins-perfmon-2.1.jar # PerfMon 监控 │ │ └── json-lib-2.4-jdk15.jar # Beanshell JSON 支持 │ └── mysql-connector-java-5.1.47.jar # JDBC 驱动 ├── tests/ │ ├── api/ │ │ ├── login.jmx # 手写 JMX,无录制痕迹 │ │ └── upload.jmx # 中文文件名已 Base64 编码 │ └── db/ │ └── order_insert.jmx # JDBC 压测脚本 ├── reports/ # 每次 `-e -o` 生成的 HTML 报告存档 └── logs/ # jmeter.log + result.jtl 按日期归档最关键的三个习惯:
- 永不修改原始 ZIP:所有定制化都在解压后的独立目录完成,
jmeter-2.11.zip本身是只读的黄金镜像; - JMX 文件禁止 GUI 保存:每次修改后,用
xmllint --format格式化 XML,用git diff审计变更,确保无隐藏属性污染; - 压测前必跑 smoke test:用
./jmeter -n -t tests/api/smoke.jmx -l /dev/null验证环境连通性,10 秒内不出错才开始正式压测。
JMeter 2.11 不是过时的代名词,它是压测领域的“机械手表”——没有智能芯片,但走时精准、故障率低、十年不坏。当你需要的不是花哨报表,而是某个 TCP FIN 包的精确时序、某个 HTTP Header 的原始字节、某个数据库事务的绝对隔离,那么这个 ZIP 包就是你的后悔药。它不教你新东西,但它让你少踩 80% 的环境坑。希望帮到你。
本文还有配套的精品资源,点击获取