1. 项目概述:从脚本录制到全场景覆盖
最近在团队里做性能压测和接口自动化回归,发现很多同事还在手动写JMeter脚本,一个复杂的业务流要折腾大半天。其实JMeter自带的录制功能(HTTP(S) Test Script Recorder)和第三方插件(如BlazeMeter的Chrome扩展)能极大提升脚本生成效率,而且生成的脚本经过简单处理,就能直接用于接口自动化测试场景。这不仅仅是“偷懒”,更是一种将性能测试左移,与自动化测试资产复用的高效实践。无论是刚接触性能测试的新手,还是想优化流程的老手,掌握这套方法都能让你事半功倍。本文就基于我多年的实战经验,拆解如何利用JMeter快速生成压测脚本,并平滑过渡到接口自动化测试。
2. 核心思路与工具选型背后的考量
2.1 为什么选择录制而非纯手写?
手动编写JMeter脚本(添加线程组、HTTP请求、参数化、断言等)是基本功,但对于复杂的多步骤业务场景(例如:登录->浏览商品->加入购物车->下单->支付),手动构建耗时耗力且容易出错。录制功能的核心理念是“捕获真实流量”,其优势在于:
- 保真度高 :直接捕获浏览器或客户端发出的真实请求,包括所有Headers、Cookies、动态参数(如
JSESSIONID,token,VIEWSTATE等),避免了手动模拟时可能出现的遗漏或错误。 - 效率飞跃 :对于包含几十个甚至上百个请求的业务流,录制可以在几分钟内完成基础脚本搭建,将工程师的时间从重复劳动中解放出来,聚焦于更重要的测试设计、参数化和结果分析。
- 学习与逆向工程 :对于不熟悉的系统,录制是快速了解其接口调用顺序、参数结构和依赖关系的绝佳方式。
当然,录制生成的“毛坯”脚本不能直接用于压测或自动化,必须经过“精装修”:删除冗余请求(如静态资源 .js , .css , .png )、处理动态参数关联、添加断言和逻辑控制器等。这是一个“从有到优”的过程,远比“从无到有”轻松。
2.2 JMeter录制方案对比与选型
JMeter主要提供两种录制方案,选择哪种取决于你的具体场景:
方案一:JMeter内置的HTTP(S) Test Script Recorder 这是最经典、最稳定的方案。JMeter本身作为一个代理服务器运行,你需要将浏览器或系统的网络代理设置为JMeter的代理地址(默认 localhost:8888 )。所有流经该代理的HTTP/HTTPS流量都会被JMeter捕获并生成对应的采样器(Sampler)。
- 优点 :原生支持,无需额外安装;可录制任何支持配置代理的客户端(桌面应用、移动端APP等);功能全面,可过滤请求。
- 缺点 :需要手动配置浏览器代理,且需要为JMeter安装JMeter根证书以录制HTTPS流量,步骤稍显繁琐。
- 适用场景 :需要录制非浏览器流量、或追求环境稳定可控的测试。
方案二:BlazeMeter Chrome扩展(或类似录制插件) 这是一个安装在Chrome浏览器中的插件。你在浏览器中操作业务,插件直接捕获DevTools Network中的请求,并生成一个 .jmx 脚本文件或可以直接导入JMeter的链接。
- 优点 :配置极其简单,一键录制;自动处理HTTPS证书问题;通常能生成更清晰、结构更好的脚本(如自动将同域名请求分组)。
- 缺点 :依赖Chrome浏览器和插件生态;通常只能录制浏览器内的流量。
- 适用场景 :快速录制基于Web的业务流程,追求上手速度。
实操心得 :对于大多数Web系统性能测试,我推荐新手从 BlazeMeter扩展 开始,快速获得成就感。对于需要录制APP接口或更复杂协议的场景,则必须使用 内置代理 。团队内部可以统一工具链,提升协作效率。
3. 详细实操:使用内置代理录制压测脚本
我们以JMeter 5.6.3版本为例,详细走通内置代理录制流程。这是理解录制原理的基石。
3.1 环境准备与代理服务器配置
首先,启动JMeter,创建一个新的测试计划(Test Plan)。
- 添加线程组 :右键测试计划 ->
Add->Threads (Users)->Thread Group。这里可以先简单设置,录制完再调整压测参数。 - 添加录制控制器 :右键线程组 ->
Add->Logic Controller->Recording Controller。所有录制的请求默认都会放在这个控制器下,方便统一管理。 - 设置HTTP(S) Test Script Recorder :
- 在工作台(Workbench)上右键 ->
Add->Non-Test Elements->HTTP(S) Test Script Recorder。 - 关键配置:
-
Port: 代理端口,默认8888,可自定义。 -
Target Controller: 选择我们刚创建的Recording Controller。 -
Grouping: 建议选择Put each group in a new controller,这样能按页面或路径对请求进行初步分组。 -
URL Patterns to Include/Exclude: 这是过滤关键! 务必在Exclude中添加.*\.(js|css|PNG|jpg|jpeg|gif|ico|woff|woff2|ttf|svg).*,以排除静态资源请求,避免压测脚本充斥大量无意义的图片、样式表请求,影响压测核心目标。
-
- 在工作台(Workbench)上右键 ->
3.2 安装JMeter根证书以录制HTTPS
这是录制HTTPS网站必须的一步,否则只能录制HTTP请求。
- 在
HTTP(S) Test Script Recorder界面,点击Start按钮。 - JMeter会在其
bin目录下生成一个证书文件ApacheJMeterTemporaryRootCA.crt。 - 你需要将此证书导入到你的 浏览器 或 系统 的受信任根证书颁发机构中。
- Chrome/Edge (Windows) : 打开设置 -> 隐私和安全 -> 安全 -> 管理设备证书 -> 受信任的根证书颁发机构 -> 导入,选择上述
.crt文件。 - macOS : 双击
.crt文件,打开钥匙串访问,将其添加到“系统”或“登录”钥匙串,并信任该证书。
- Chrome/Edge (Windows) : 打开设置 -> 隐私和安全 -> 安全 -> 管理设备证书 -> 受信任的根证书颁发机构 -> 导入,选择上述
- 导入成功后,重启浏览器。
3.3 配置浏览器代理并开始录制
- 以Chrome为例(也可使用SwitchyOmega等插件):
- 打开浏览器设置 -> 系统 -> 打开计算机的代理设置。
- 在Windows网络设置或macOS网络高级设置中,配置手动代理:地址
127.0.0.1,端口8888(与JMeter中设置一致)。
- 回到JMeter,点击
HTTP(S) Test Script Recorder上的Start按钮。 - 在浏览器中,正常操作你的待测Web应用(例如:登录、搜索、下单)。
- 所有操作发出的请求都会实时出现在
Recording Controller下。 - 操作完成后,在JMeter中点击
Stop按钮停止录制。
3.4 脚本精加工:从“毛坯”到“精装”
录制生成的脚本可以直接运行,但为了有效的压测和自动化,必须进行以下关键处理:
-
清理与组织 :
- 删除
Recording Controller下所有静态资源请求(如果过滤模式没完全生效)。 - 使用
Transaction Controller将属于一个业务事务的多个请求组合起来(如“用户登录事务”包含获取验证码、提交登录两个请求),便于统计事务响应时间。 - 给每个
HTTP Request起一个有意义的名称,如API_Login_Submit。
- 删除
-
处理动态参数(关联) : 这是最核心的一步。录制的脚本包含了当时会话的固定值(如
token,orderId),但压测时每个虚拟用户(线程)必须使用自己的值。- 使用后置处理器 :在产生动态参数的请求后,添加
Post Processors->Regular Expression Extractor或JSON Extractor,将响应中的动态值(如"token":"(.*?)")提取到一个变量(如${auth_token})中。 - 在后续请求中引用 :在需要该参数的请求中,将原固定值替换为变量引用
${auth_token}。
- 使用后置处理器 :在产生动态参数的请求后,添加
-
参数化输入数据 : 避免所有用户用同一账号登录。使用
CSV Data Set Config组件,连接一个包含多行用户名、密码的CSV文件,在登录请求中引用${username},${password}。 -
添加断言(关键!) : 压测不仅要看是否出错,还要看结果是否正确。为关键请求添加
Response Assertion,检查响应码是否为200,或响应文本中包含特定关键字(如登录成功后的“欢迎”字样)。 -
添加监听器(仅用于调试) : 调试脚本时,可以添加
View Results Tree来查看每个请求和响应的详情。 但在正式压测时,务必禁用或删除所有监听器 ,因为它们会消耗大量内存,严重影响JMeter本身的性能。
注意事项 :关联(Correlation)是性能测试脚本开发的难点。务必仔细分析前后请求的参数传递关系。一个技巧是:在
View Results Tree中对比录制时的请求和手动重放失败的请求,差异点往往就是需要关联的动态参数。
4. 进阶:将压测脚本转化为接口自动化测试场景
一套好的压测脚本,已经包含了完整的业务流、正确的参数化和结果校验(断言)。这恰恰也是接口自动化测试的核心要素。只需稍作调整,即可复用。
4.1 思维转换:从“并发负载”到“功能验证”
- 目标变化 :压测关注系统在并发下的性能指标(TPS、RT、错误率);自动化测试关注单次执行的功能正确性、接口契约的稳定性。
- 脚本调整 :
- 线程组设置 :将压测脚本中可能包含的
Thread Group(模拟多用户)改为仅1个线程、1次循环,或者使用Simple Controller来组织测试用例。 - 增强断言 :自动化测试对断言的要求更严格。除了响应码和文本,应增加对响应JSON/XML结构的校验(使用
JSON Assertion或JSR223 Assertion),对特定字段值进行验证。 - 添加测试逻辑 :使用
If Controller、While Controller等来处理不同的测试分支。例如,如果登录失败,则跳过后续的流程。 - 结果输出与报告 :自动化测试需要清晰的通过/失败报告。可以使用
JSR223 PostProcessor结合Groovy脚本,将测试结果(用例名、状态、耗时)写入日志文件或数据库。更专业的做法是集成到持续集成(CI)流程,使用Ant或Jenkins的JMeter插件来生成HTML报告。
- 线程组设置 :将压测脚本中可能包含的
4.2 构建可维护的自动化测试资产
-
模块化设计 :
- 将通用操作(如登录、获取令牌)封装成独立的
Test Fragment或保存在单独的.jmx文件中,通过Module Controller或Include Controller进行调用。实现“一次编写,多处复用”。 - 使用
User Defined Variables配置全局环境变量(如测试环境URL、预置账号),便于在不同环境(测试、预生产)间切换。
- 将通用操作(如登录、获取令牌)封装成独立的
-
数据驱动 :
- 自动化测试同样需要参数化。将测试用例的输入和预期输出存储在CSV或Excel中,使用
CSV Data Set Config读取,实现一条脚本覆盖多组测试数据。
- 自动化测试同样需要参数化。将测试用例的输入和预期输出存储在CSV或Excel中,使用
-
集成到CI/CD :
- 使用命令行模式执行JMeter脚本:
jmeter -n -t [脚本.jmx] -l [结果.jtl] -e -o [报告输出目录] - 在Jenkins等CI工具中配置Job,定时或触发执行该命令,并归档生成的HTML报告。这样,每次代码提交后都能自动运行接口回归测试。
- 使用命令行模式执行JMeter脚本:
4.3 一个简单的自动化测试示例结构
假设我们将一个“用户登录并查询信息”的压测脚本转化为自动化测试脚本,结构如下:
Test Plan
├── User Defined Variables (定义 base_url, login_path等)
├── Thread Group (线程数:1, 循环次数:1)
│ ├── CSV Data Set Config (读取 test_accounts.csv)
│ ├── Transaction Controller: TC_Login
│ │ ├── HTTP Request: POST /api/login
│ │ │ ├── Body Data (引用 ${username}, ${password})
│ │ │ └── JSON Extractor (提取 token 到 ${auth_token})
│ │ └── Response Assertion (验证响应码200, 消息体包含“success”)
│ ├── If Controller (条件: ${auth_token} != null)
│ │ └── Transaction Controller: TC_QueryUserInfo
│ │ ├── HTTP Request: GET /api/user/info
│ │ │ └── Header Manager (添加 Authorization: Bearer ${auth_token})
│ │ └── JSON Assertion (验证 jsonPath $.data.username 等于 ${username})
│ └── Simple Controller: Teardown (可添加清理操作,如退出登录)
└── 监听器 (仅调试时用,如 View Results Tree)
5. 实战避坑指南与性能优化
5.1 录制与回放常见问题排查
即使按照步骤操作,录制和脚本调试过程中也难免踩坑。下表总结了一些典型问题及解决方案:
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
| 录制不到任何请求 | 1. 浏览器代理未正确设置。 2. JMeter代理未启动。 3. 防火墙/安全软件阻止。 | 1. 检查浏览器代理设置是否为 127.0.0.1:8888 。 2. 确认JMeter中 HTTP(S) Test Script Recorder 已点击 Start ,且端口无冲突。 3. 临时关闭防火墙或安全软件试试。 |
| HTTPS网站录制失败或报证书错误 | 1. JMeter根证书未安装或不受信任。 2. 网站使用不兼容的SSL协议或密码套件。 | 1. 重新检查证书安装步骤,确保证书已导入到“受信任的根证书颁发机构”。 2. 在JMeter的 HTTP(S) Test Script Recorder 的 SSL Certificate 区域,尝试调整 Client certificate store 类型。 |
| 脚本回放失败,但浏览器操作正常 | 1. 动态参数未关联 (最常见)。 2. 请求头(Headers)缺失或不同。 3. 请求体格式错误。 | 1. 使用 View Results Tree 对比录制和回放的请求详情,重点检查差异参数,使用正则提取器关联。 2. 检查 Header Manager ,确保 User-Agent , Content-Type , Cookies 等与浏览器一致。 3. 检查 Body Data 格式,是JSON还是表单,确保编码正确。 |
| 回放时出现403 Forbidden或404 | 1. 请求URL路径或参数因时间或会话变化已失效。 2. 缺少必要的Referer或Origin头。 | 1. 检查URL中是否包含时间戳等动态部分,可能需要关联或参数化。 2. 添加 Header Manager ,补充 Referer 等头信息。 |
5.2 JMeter压测本身的性能调优
当你用JMeter去压测一个高并发系统时,JMeter本身也可能成为瓶颈。以下优化技巧能让你用更少的资源发起更高的压力:
- 禁用GUI,使用命令行模式 :这是最重要的原则。正式压测永远使用
jmeter -n -t test.jmx -l result.jtl命令在无界面模式下运行,资源消耗极低。 - 精简监听器 :如前所述,
View Results Tree、Aggregate Report等监听器在运行时会消耗大量堆内存。正式压测时,只保留必要的监听器(如Summary Report),或使用Backend Listener将数据异步发送到InfluxDB,再由Grafana展示。 - 调整JVM参数 :编辑JMeter的
bin/jmeter(Linux/mac)或bin/jmeter.bat(Windows)文件,调整HEAP大小。例如,对于8G内存的压测机,可以设置:HEAP="-Xms4g -Xmx4g -XX:MaxMetaspaceSize=512m”。避免Xmx设置过大导致GC停顿。 - 使用分布式压测 :单机JMeter能模拟的线程数有限(通常几千)。需要更大并发时,使用多台Slave机器进行分布式压测,由一台Master控制机控制。注意网络带宽和Slave机自身的资源监控。
- 脚本层面优化 :
- 合理使用定时器 :在需要控制TPS(每秒事务数)的场景下,使用
Constant Throughput Timer或Precise Throughput Timer,比单纯增加线程数更科学。 - 减少不必要的采样器 :清理脚本,确保每个HTTP请求都是业务必需的。
- 参数化文件优化 :如果使用巨大的CSV文件,考虑将其放入RAM Disk(内存盘)以减少IO延迟。
- 合理使用定时器 :在需要控制TPS(每秒事务数)的场景下,使用
5.3 关于“端口占用”问题的高阶处理
在长时间压测或高并发下,即使线程数不多,JMeter也可能出现“Address already in use: connect”错误。这是因为TCP连接关闭后进入 TIME_WAIT 状态,会占用端口一段时间(默认2MSL,约60-120秒),导致本地端口资源被耗尽。
解决方案:
-
操作系统层面调整TCP参数 (Linux示例):
# 缩短TIME_WAIT超时时间 sysctl -w net.ipv4.tcp_fin_timeout=30 # 开启TIME_WAIT端口快速回收和重用 sysctl -w net.ipv4.tcp_tw_recycle=1 # 注意,该参数在高版本内核中已移除,且NAT环境下可能有问题 sysctl -w net.ipv4.tcp_tw_reuse=1 # 增大本地端口范围 sysctl -w net.ipv4.ip_local_port_range="1024 65535"注意 :修改系统参数需谨慎,特别是在生产服务器上。
tcp_tw_recycle在较新的Linux内核中已被移除,且可能与负载均衡器不兼容。更推荐使用下面的JMeter配置方案。 -
JMeter配置优化 :
- 在
HTTP Request的“高级”选项卡中,或HTTP Request Defaults中,勾选Use keepalive。这会使连接复用,减少TCP握手和挥手次数,从根本上减少TIME_WAIT连接的产生。 - 在
HTTP Request的“实现”中选择HttpClient4,并配置连接池。在jmeter.properties文件中设置:
合理的连接池配置可以大幅提升效率和减少端口占用。httpclient4.time_to_live=60000 # 连接存活时间(毫秒) httpclient4.max_total_connections=200 # 全局最大连接数 httpclient4.default_max_per_route=100 # 每个路由(目标主机)最大连接数
- 在
-
增加压测机 :如果单机优化后仍遇到瓶颈,最直接有效的方法是增加压测Slave机,将压力分散。
6. 现代化实践:与持续测试平台集成
手动运行JMeter脚本的时代正在过去。将JMeter脚本集成到持续集成/持续部署(CI/CD)流水线和专业的测试平台中,是实现高效、稳定性能测试和自动化测试的必然趋势。
6.1 集成到CI/CD:Jenkins + JMeter + Performance Plugin
这是最经典的自动化流水线集成方案。
- 环境准备 :在Jenkins服务器上安装JMeter和必要的插件(如
Performance Plugin)。 - 创建Jenkins Job :
- 在“构建”步骤中,添加“Execute shell”或“Windows batch command”,调用JMeter命令行执行脚本。
jmeter -n -t $WORKSPACE/performance/test_plan.jmx -l $WORKSPACE/result.jtl -e -o $WORKSPACE/report - 在“构建后操作”中,添加“Publish Performance test result report”,指定生成的
result.jtl文件路径。该插件会自动解析结果,并在Jenkins Job页面上生成趋势图,展示TPS、响应时间、错误率等关键指标的历史变化。
- 在“构建”步骤中,添加“Execute shell”或“Windows batch command”,调用JMeter命令行执行脚本。
- 设定质量关卡 :可以在Jenkins Pipeline脚本中,通过解析
result.jtl或使用插件提供的API,判断本次压测结果是否达标(如平均RT<1s,错误率<0.1%)。如果不达标,则让构建失败或发出警告,实现性能回归的自动拦截。
6.2 使用专业测试平台:MeterSphere
对于追求更完善管理、协作和报告能力的团队,开源的一站式测试平台MeterSphere是更好的选择。它底层兼容JMeter,但提供了Web化的操作界面。
- 脚本管理 :将
.jmx文件上传到MeterSphere的“性能测试”模块,或直接使用其界面创建测试(类似JMeter GUI,但更友好)。脚本、测试数据、参数文件都可以在平台内统一版本化管理。 - 测试执行与监控 :在平台上配置压测参数(并发数、时长、加压方式),并指定测试资源池(一组安装了MeterSphere Agent的压测机)。执行测试时,平台会自动分发脚本并收集结果。
- 实时监控与报告 :测试执行过程中,平台提供实时仪表盘,展示TPS、RT、并发数、服务器资源(CPU、内存)等监控图表。测试结束后,自动生成详细的多维度HTML报告,并支持与历史测试结果对比。
- 接口自动化集成 :MeterSphere同样支持接口自动化测试。你可以直接将调试好的JMeter脚本导入为接口自动化测试场景,编排测试用例,设置断言,并集成到CI/CD中定时执行。
从手写脚本到录制生成,从单机压测到分布式集群,从本地运行到CI/CD集成,JMeter的能力边界在不断扩展。掌握录制生成脚本的技巧,是提升性能测试效率的第一个关键台阶。而认识到压测脚本与自动化测试脚本的同源性,并主动将其转化为可复用的测试资产,则是测试工程师提升自身价值、推动测试左移的更重要一步。工具是死的,思路是活的。最好的脚本不是最复杂的,而是最能高效、准确反映业务场景并易于维护的那一个。
993

被折叠的 条评论
为什么被折叠?



