ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

JMeter录制脚本全链路指南:从抓包到参数化压测实战

JMeter录制脚本全链路指南:从抓包到参数化压测实战 第一次打开JMeter的新手十个里有九个会先找“录制”按钮——不是大家懒而是被测系统的请求结构有时候确实复杂手写HTTP请求容易漏掉Header、漏掉隐含参数。“录制测试脚本”这件事在JMeter里有一套完整的方法论它不是简单地抓包回放而是要让你在短时间内生成一个能跑、能压、能出报告的脚本骨架。这篇文章就围绕JMeter录制脚本的完整链路展开从方案选型、环境配置、HTTPS证书处理到录制后的整理增强再到高频报错排查把整个流程里值得注意的细节都过一遍。适合刚上手JMeter、或者已经能用JMeter做简单接口测试但一直没把录制用明白的测试工程师参考。1. 录制方案选型先搞清楚你需要的到底是不是“录”1.1 录制测试脚本的本质是什么JMeter的录制功能通俗理解就是在本机架一个“监听员”你打开浏览器正常操作被测系统JMeter把这些操作发出的HTTP请求全部记录下来自动转成一个个Sampler最后组合成一份.jmx脚本。这个机制的学名叫HTTP(S) Test Script Recorder本质上是一个本地监听端口它不关心你是点了按钮还是拖了页面只关心浏览器发出了什么请求、带了什么参数、收到了什么响应。很多人把录制想简单了以为“录完就能压”。实际上录制只是拿到一份原始素材素材里包含大量无用请求比如图片、CSS、JS、埋点统计这些基本都要过滤掉同时真实用户的操作往往带有动态数据比如登录后拿到的token、表单里的防伪标记这些如果不做参数化脚本就只能跑一次。所以我把录制定位成“快速生成脚本骨架”的手段真正决定脚本质量的是录制之后那一步整理增强。1.2 三套录制方案的取舍先说Badboy。这是一个老牌网页录制工具录制完可以导出成JMeter能识别的.jmx文件优点是录制时有可视化界面能看着脚本结构一步步点缺点是已经停止维护很久了和JMeter新版的兼容性越来越差遇到前后端分离的动态请求录制效果并不理想。现在新入行的测试同学没必要再学它。再说JMeter内置的HTTP(S) Test Script Recorder。这是我最推荐的方式JMeter自带不需要额外装软件录制出来的请求天然就是JMeter的Sampler结构和线程组、断言、参数化功能无缝衔接。缺点是需要手动在浏览器设置监听端口HTTPS还要处理证书稍微有点门槛但门槛不高。还有第三种用Fiddler或Charles这类抓包工具录制后转成脚本。这种方式录得更细能看到每个请求的完整时序但转换成JMeter脚本时依赖导出插件请求头、Cookie经常丢后期修正成本比前两种都高适合分析问题不适合快速生成压测脚本。我的建议很明确能用内置录制器就别折腾第三方工具。尤其是JMeter 5.x之后的版本证书处理、域名过滤、URL重写这些细节都做得比较完善整套流程保持在JMeter生态里后期维护成本最低。Badboy那一类工具在2010年前后很流行现在用反而是给自己添堵。2. 录制准备与核心配置把监听端口这件事想明白2.1 环境准备与基础安装先说安装。去Apache JMeter官网下载找“Download Releases”入口下载zip包Windows或者tgz包Linux/macOS。JMeter是纯Java应用依赖JDK 8以上所以第一步先把JDK装好。下载后解压到纯英文路径目录里会有bin、lib、docs等文件夹lib/ext目录专门放扩展插件。Windows下双击bin/jmeter.bat启动Linux/macOS用bin/jmeter.sh。启动后如果觉得界面字体小不要急着找设置按钮——JMeter的界面字体在bin目录下的jmeter.properties里调找到jsyntaxtextarea.font.size和jmeter.hidpi.mode等配置项也可以直接在界面“选项→外观”里切换。我习惯把字号调到15左右长时间看聚合报告不费眼。安装本身不算复杂但我见过不少人卡在“启动闪退”上要么JDK版本太低要么JAVA_HOME没配好要么解压路径带了中文。JMeter 5.x要求JDK 8及以上JDK 9到11也能跑但有些插件兼容性不好所以如果只是做常规HTTP接口测试装JDK 8稳定版最省心。2.2 配置HTTP(S) Test Script Recorder的完整步骤打开JMeter先创建一个测试计划然后按下面顺序操作。添加线程组右键测试计划添加→线程用户→线程组。线程数可以先设为1录制阶段不需要并发。添加录制控制器右键线程组添加→逻辑控制器→录制控制器。它的作用是给录制到的请求一个存放位置同时方便你只录制不跑。添加HTTP(S) Test Script Recorder右键测试计划添加→非测试元件→HTTP(S) Test Script Recorder。配置监听端口在录制器面板里端口默认8888这个端口就是浏览器要走的监听端口。如果本机已有程序占用8888改成8889或其他空闲端口。设置目标控制器选择刚才添加的“录制控制器”这样录制到的请求才会落到线程组下面的控制器里而不是散落在测试计划根部。配置“HTTPS Domains”这里填被测系统的域名作用是让JMeter自动处理该域名下的HTTPS证书校验减少录制时的证书报错。这里有一个新手最容易漏的地方录制控制器必须在线程组下面否则录制时请求不会进线程组后面压测时你会找不到那些Sampler。还有一个点录制之前先在线程组下面加一个“察看结果树”监听器这样录制过程中就能实时看到当前请求有没有录进来不用录完再去找。2.3 浏览器监听设置与HTTPS证书导入监听端口配好后还要让浏览器把流量交给JMeter的这个端口。这个动作在浏览器里叫“手动配置代理”这里说的是本机测试环境的配置只是把浏览器的请求导向本机的JMeter端口不涉及任何外部网络。以Firefox为例打开设置→网络设置→手动配置代理→HTTP代理填127.0.0.1端口填8888勾选“也适用于HTTPS”。配置完成后打开浏览器访问一个HTTP页面回到JMeter的录制控制器里能看到请求一条条冒出来说明监听成功。但如果被测系统是HTTPS你还会遇到证书报错——浏览器会提示“您的连接并不安全”因为JMeter动态生成的证书不是浏览器默认信任的。解决思路是导出并信任JMeter证书。在录制器面板点击“启动”后JMeter会自动生成一个ApacheJMeterTemporaryRootCA证书。浏览器访问http://127.0.0.1:8888就能下载到这个证书文件实际会生成一个crt文件。把这个证书导入到浏览器的“证书颁发机构”列表中勾选“信任此CA来标识网站”然后重启浏览器HTTPS录制就能正常走了。Firefox和Chrome的导入入口不同但思路一样先下载根证书再在浏览器设置里导入并信任。Chrome走的是操作系统级证书库Windows下要双击证书文件导入到“受信任的根证书颁发机构”。我踩过的坑证书导入后如果浏览器还报证书错误先检查系统时间是不是不对证书有效期校验对时间非常敏感。另外导入证书前要把旧的临时证书清掉否则浏览器会用旧证书导致校验失败。录完之后别忘了把浏览器的代理设置关掉否则不录制时浏览器会一直把请求丢给JMeter页面全打不开。2.4 过滤规则决定脚本质量的隐藏细节录制面板里有一个“包含/排除”正则列表这是很多教程不重视但实际非常影响脚本质量的地方。默认情况下你录一个登录页面可能录进来几十个请求图片、字体、CSS、JS、统计SDK、favicon……这些静态资源在真实用户访问时确实会产生流量但对性能测试来说如果把几十上百个静态资源的请求全部保留反而会稀释核心接口的响应时间数据让报告看起来“平均响应时间很高”但不知道瓶颈在哪。所以我在录制前一般会在“排除”里加上这几类.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)(\?.*)?过滤静态资源.*\.(map|min\.js)$过滤前端源码映射文件.*\/collect.*、.*\/metrics.*等业务无关请求根据实际项目放行或排除注意过滤规则用的是正则而不是通配符。如果你不熟悉正则最简单的办法就是先录一遍然后回来看结果树把不需要的请求的URL复制出来在排除列表里加一行对应正则。这样做的好处是脚本体积小、逻辑清晰后面加断言和参数化的时候不会乱。3. 录制之后的脚本整理与增强3.1 参数化把写死的请求数据变成可复用变量录制完成后你会发现所有请求的URL、参数、Header全部是写死的。如果脚本只跑一遍写死没问题但压测要模拟100个用户并发每个用户都带着同样的手机号、同样的订单号去请求服务端会怎么反应要么报重复数据要么触发防重机制要么缓存命中导致响应时间失真。所以参数化是录制脚本之后最必要的一步。最常用的参数化工具是CSV Data Set Config。创建一个csv文件第一行放变量名比如username,password,phone后面每行放一条测试数据。在需要参数化的请求里把原来的值替换成${username}、${password}这种变量引用。特别要注意CSV组件的几个配置项线程共享模式如果选择“当前线程组”每个线程会按顺序读取csv的一行线程之间不会重复如果选择“所有线程”多个线程会共同消费这个文件。很多人问的“同一个csv参数化文件中每个线程分块取值”对应的就是“当前线程组”模式。它会把csv按线程数分块每个线程取自己那块的数据从而保证账号不串线。遇到文件末尾Recycle循环次数如果大于数据行数建议勾选RecyclefalseStop threadTRUE避免测试数据被循环复用导致冲突。除了CSV还有一种很常见的参数化方式是从数据库取值也就是JDBC Request配合CSV或者直接配合参数的用法。做法是先配置一个JDBC Connection Configuration填写数据库URL、驱动、账号密码然后通过JDBC Request查出一批数据存到变量里供后续请求使用。比如压测下单接口先查出一批user_id再把user_id传给下一个接口。如果查询结果只有一行直接用变量名如果有多行可以配合计数器或者ForEach控制器逐条消费。数据库密码不要直接明文写在jmx里建议用JMeter的配置元件里引用环境变量避免脚本泄露。3.2 断言与提取让脚本真正会“判断”录制脚本跑起来容易但要让它自动判断“这次请求到底成没成功”就必须要加断言。最简单的断言方式是响应文本包含在请求下面加一个“响应断言”模式匹配填“操作成功”这类业务关键字如果响应里没有就会报错。这个方法很多人会但实际项目里用得更多的是提取器。因为现在的系统几乎都是前后端分离登录后token、防伪标记这类动态参数会在响应里返回。你就需要先用JSON Extractor或者正则表达式提取器把这些值提取到变量里然后在后续请求中引用。JSON Extractor在响应是JSON格式时非常好用写一个JSONPath表达式比如$.data.token匹配到之后存成变量token后面的请求在Headers里写Authorization: Bearer ${token}即可。正则表达式提取器更通用适合响应是HTML或者混合格式的场景写法是token:([^])模板取$1$。Beanshell断言是另一个高频需求点。它适合做复杂逻辑判断比如响应里返回一个错误码列表我想根据错误码做不同处理。在断言里写一段简短的Beanshell脚本可以用vars.get()去取变量用prev.getResponseDataAsString()去取响应内容然后通过Failure true;或FailureMessage ...;控制断言结果。贴一个我常用的模板String resp prev.getResponseDataAsString(); if (resp.contains(code\:200)) { Failure false; } else { Failure true; FailureMessage 业务返回码错误, 响应内容: resp; }注意Beanshell在JMeter里属于性能较差的组件压测时如果QPS要求高尽量少用或者改用JSR223Groovy。小流量验证功能时用Beanshell没问题大并发场景我建议用Groovy脚本写断言效率差好几倍。3.3 特殊场景上传文件与防伪标记录制脚本时经常遇到上传文件接口。录制时你正常选文件、上传录制下来的脚本里会看到multipart/form-data类型的请求里面有个文件路径参数。这里最需要改的是把文件绝对路径改成相对路径或者参数化我见过太多人把本地路径E:\test\照片.jpg写死到脚本里结果脚本发到别人电脑上路径不存在直接报错。正确做法是把要上传的文件放到JMeter的bin目录或者测试脚本同级目录然后参数里写相对路径如果压测机器是多台还要考虑把文件分发到每一台压测机上路径保持一致。另一个高频坑是防伪标记。很多MVC项目会校验__RequestVerificationToken防伪令牌录制脚本时往往第一次手动操作会带上这个token但脚本回放时却报“未提供必要的防伪标记”。根因是token是动态的和会话Cookie绑定每次请求前都要先从页面或者接口拿到新的token。解决办法就是上面说的提取器登录页或者首页响应里会把这个token藏在表单隐藏域里用正则提取器或者XPath提取器把它取出来在后续POST请求中用${token}替换。如果token在Cookie里联动变化还要检查Cookie管理器是否勾选了“每次迭代清除Cookie”否则上一次会话的Cookie会干扰这一次。至于RESTful参数怎么写录制的脚本里一般都能直接看到GET请求参数拼在URL后面POST请求参数在Body Data里JSON格式的直接在请求体的JSON字符串中改写。但录制下来的请求往往带着一堆没用的Header比如Accept-Language、Referer等回放时Header太多反而容易触发服务端风控建议只保留Content-Type、Authorization和必要的自定义Header。3.4 并发验证与结果导出录制脚本的最终检查脚本整理完之后先在线程组里设置线程数。第一次验证阶段线程数设为1循环1次配合察看结果树确认每一个请求都是绿色通过、响应时间正常。确认没问题后再按压测需求设置并发比如线程数100Ramp-Up Period设为10秒循环次数根据场景来。这里的Ramp-Up Period意思是100个线程在10秒内逐步启动而不是一开跑就100个线程同时打过去这个设计是为了模拟真实用户逐步进入系统的过程也能避免瞬间压垮服务端导致误判。跑完之后重点看三类数据聚合报告里的平均响应时间、90%响应时间、吞吐量错误率以及TPS曲线。具体到“模拟100用户并发报告”你在聚合报告里能看到每个请求的样本数、平均响应时间、中位数、异常%等指标。如果异常%不为0双击请求对应的行结合断言失败信息定位是参数化数据冲突还是服务器报错。察看结果树里的请求可以通过右键导出全部或者部分sample result保存为JTL或XML格式方便后续做二次分析和留存记录。导出的时候记得勾选“保存响应数据”否则只有请求摘要没有响应报文出了问题很难追溯。4. 高频报错速查与排查实录4.1 录不上、证书信任与连接异常第一个高频错误是录不上浏览器配置了监听但是JMeter里没有请求进来。排查顺序是这样先看监听端口有没有被占用命令行执行netstat -ano | findstr 8888再看浏览器代理地址和端口是否和JMeter一致最后看浏览器有没有开第三方插件拦截代理。还有种情况是录制时指定了HTTPS Domains确保域名和实际访问地址完全一致带不带www也要一致有时候多了个前缀就录不上。第二个高频错误是HTTPS录不了页面显示证书无效。这类问题九成出在证书导入环节。检查顺序证书有没有导入到正确的证书存储区浏览器有没有重启系统时间是否正确。另外还有一个冷门原因JMeter生成的证书有效期是7天如果你用的是很老的JMeter版本并且跨了星期证书可能已经过期重新启动录制器生成新证书即可。第三个高频错误是运行时出现java.io.IOException: Error writing to server。这个报错一般出现在发请求的瞬间本质是JMeter向服务器写数据时连接被重置常见原因是服务端主动断开——比如你压测QPS过高服务端连接池满了直接RST也有可能是请求头带了非法字符或者Content-Length不对导致服务端解析失败。排查思路是先降并发确认是不是过载问题如果单线程也报就抓一下请求内容看有没有特殊字符。实际上很多时候是录制时把一些响应相关的头比如Content-Length也带上了回放时造成冲突删掉这类请求头就好。4.2 文件冲突、乱码与数据重复“文件已经存在”这个报错通常出现在察看结果树导出结果或者自己配置了输出文件时你指定的文件名已经存在JMeter默认会拒绝覆盖。解决办法是在文件配置里勾选“Overwrite”或者“Append”或者每次运行前先删掉旧文件。如果你是用命令行跑压测还可以在命令里加时间戳动态生成文件名比如result_20250101123000.jtl既避免冲突又能保留每次压测的记录。乱码问题也比较常见。录制脚本或察看结果树里中文变成??或者%E4%B8%AD一般是编码不一致。第一种方案是确保被测系统响应是UTF-8然后在察看结果树里切换编码显示第二种是在取样器的Content Encoding里明确填UTF-8第三种是修改jmeter.properties里的sampleresult.default.encodingUTF-8。如果数据库里的中文乱码那就是JDBC配置里没有加characterEncodingutf8加上即可。数据重复的问题前面说过优先检查CSV参数化的线程共享模式和Recycle配置别让两条线程拿了同一行数据。4.3 插件扩展与压测执行节奏热搜里看到有人问jmeter下载mqtt插件、插件包安装这类问题一并说下。JMeter的插件生态很丰富安装路径一般是先下载JMeter Plugins Manager一个jar包放到lib/ext目录重启JMeter后菜单栏会出现“选项→Plugins Manager”。在里面勾选需要的插件比如MQTT协议支持、自定义线程组、PerfMon监控JMeter会自动下载安装。但我的经验是插件能少装就少装插件会改变JMeter的默认线程实现和部分行为装多了之后升级、排错都会变麻烦。尤其是压测脚本如果依赖了某个第三方插件换一台没装插件的机器就跑不起来。尽量用JMeter原生能力解决问题实在需要MQTT这种原生不支持的协议再考虑插件。最后分享一个关于执行节奏的心得。压测不是“脚本跑完看报告”就结束了合理的流程是先小并发冒烟比如5个线程跑3分钟确认脚本参数化没问题再逐步升到目标并发的一半观察TPS和错误率变化最后才打到目标并发稳定跑10到15分钟取数据。这样即使压出问题也能区分到底是脚本问题还是环境问题不至于一上来就稀里糊涂压出一堆Error最后还不知道锅该甩给谁。5. 关于录制脚本这件事我最后想说的常在测试圈看到两种极端一种人觉得录制是“小白才用”的功能高手都手写脚本另一种人录完脚本拿过来就直接压出了问题就甩锅给工具。这两种我都经历过。实际上录制功能最大的价值不是帮你省掉写请求的时间而是帮你快速理解一个陌生系统的请求链路——登录页跳了哪些接口、下单时带了哪些参数、退出时清理了哪些会话这些信息在手写脚本时很容易遗漏但录制一遍就全暴露出来了。我自己做压测项目的习惯是录制只作为第一步拿到脚本骨架后一定会做三件事——过滤静态资源、参数化所有动态值、给关键接口补断言。这三个动作做完脚本才算真正能用于压测。你花在脚本整理上的时间通常会在压测执行阶段几倍地赚回来因为不用一边压一边排查“这个error到底是脚本问题还是服务端问题”。如果你刚开始接触JMeter不妨从一个小项目开始练手拿一个自己部署的Web应用完整走一遍录制、整理、参数化、并发验证的流程。等这套流程跑顺了再去看那些所谓的“高手脚本”你会发现它们的核心骨架和你自己整理出来的脚本其实没什么两样。
返回列表