
Jmeter 录制压测脚本这件事表面看只是点几下、把业务流程走一遍真上手就知道四种常见路子各有各的脾气有的两分钟就能出脚本五分钟就报证书错误有的稳得像块石头但光配证书就能劝退一半人。我从早期内网的老 B/S 系统一路做到云上微服务集群的并发验证前前后后换过至少四种录制方式踩过的坑攒了满满两页笔记这篇就把这四种方式的原理、边界、完整操作步骤和排查经验一次交代清楚。先把概念划清楚。性能测试里说的录制指把浏览器或客户端真实发出的 HTTP/HTTPS 请求流量捕获下来转成 Jmeter 可以直接执行的 .jmx 脚本。这跟直播圈里说的录制完全不是一回事后者是把推流画面存成文件跟压测八竿子打不着所以标题里只写录制两个字经常有朋友点进来才发现走错门这里先说明白。读完之后你能拿到什么四种录制方式各自的完整操作流程、一张选型对比表、录制完成后的脚本改造思路参数化、关联、断言、定时器外加一份录制与加压阶段的高频问题速查表。刚接触 Jmeter 的同学可以照着步骤一步步走已经在做性能测试的同行可以直接跳到选型和排查那两节抄作业。1. 录制方式怎么选先看四种路子的底层机制1.1 手工拼接口和录制脚本各管哪一段很多人一上来就问到底该录还是该手写这个问题其实问偏了。真实项目里这两件事从来不是二选一而是分工。录制负责把业务流程的骨架搭出来手写负责把骨架上的关节补全。我自己的判断标准很朴素一个业务场景如果涉及超过八个接口串联或者链路里带着前端框架异步刷出来的动态参数那纯手写的成本会高得离谱。一个下单流程从登录、选商品、加购物车、算价、下单、支付回调到查订单中间还夹着一堆埋点和轮询接口手工一个个拼光抄参数就要大半天还容易漏掉某个中间请求。这种情况下录制就是省时间的正路二十分钟录完再花两三个小时清理和关联整体比手写快得多。反过来说如果只是一个单接口的压测参数结构清楚、没什么依赖那直接手写反而更干净。录制出来的脚本会带一堆冗余的 HTTP 头、无关的采样器和没用的断言清起来也麻烦。所以判断逻辑是链路长、依赖多、需要复现真实用户行为用录制链路短、参数固定、需要精确控制并发模型用手写。还有一个容易被忽略的点录制出来的脚本从来不等于能用的压测脚本。它只是一个请求序列快照里面所有动态生成的东西都是死的。回放的时候服务端一校验要么报参数无效要么直接返回登录失效。所以真正的功夫在录制之后这一点后面第 7 节会展开讲。1.2 四种录制方式的横向对比表与选型口诀市面上流传的四种方式版本不少但真正在项目里能落地的就这么四类。我把它们的核心机制、代价和适用边界整理成一张表选型的时候直接对着看。录制方式核心原理HTTPS 支持移动端/App脚本干净度典型适用场景Badboy 录制内置浏览器内核直接录制导出 JMX依赖内置内核老站点可用不支持中等冗余较多老式表单型 B/S 系统Jmeter 自带代理录制本地起 HTTP 代理拦截浏览器流量需要装根证书支持完整手机设代理后支持高可控过滤主流 Web 项目链路复杂抓包工具转 JMX/HAR抓包后导出会话再转换抓包工具侧处理证书支持App 场景主力中等需要二次清洗移动端、只录特定接口浏览器扩展录制扩展监听浏览器网络栈天然支持无需装证书不支持一般可能带插件依赖快速出草稿、纯浏览器流程选型口诀我总结成三句。第一句是Web 项目优先用自带代理因为过滤规则、目标控制器、分组策略都在 Jmeter 内部录完就是干净的原生元件不会引入第三方插件依赖。第二句是App 和只录局部用抓包因为手机端流量绕不开抓包工具而浏览器的 DevTools 可以直接导出 HAR零依赖零安装。第三句是要快就上浏览器扩展代价是导出的脚本可能带着别人家的元件类打开报错还得补插件。Badboy 我把它放在最后一档。不是说它不能用而是它的内置浏览器内核实在太老今天大部分前端工程在它里面根本渲染不出来录出来的脚本常常只有一条主文档请求。留着了解可以新项目别指望它。提示无论用哪种方式录录之前先把浏览器缓存清掉、无关标签页关掉、代理只开一个。多开一个代理插件流量走岔了录出来的东西会让你怀疑人生。2. 动手之前Jmeter 环境搭建与几个必改的默认配置2.1 JDK、安装包与目录选择的三个硬约束Jmeter 本身是个纯 Java 应用所以第一件事是把 JDK 装好。新版本的 Jmeter 对 JDK 版本有要求稳妥的做法是装 JDK 8 或者 JDK 17 这两个长期维护版本别用太新的实验版本否则某些插件会加载失败。装完之后命令行敲java -version能正常输出版本号才算过关。这里有个新手常犯的错误只装了 JRE 没装 JDK运行 Jmeter 的时候报找不到编译器其实是你少了开发包。第二个约束是解压目录。Jmeter 是绿色包官网下载压缩包解压即用不需要安装程序。但解压路径绝对不能带中文、空格和特殊符号。这不是洁癖是实打实的坑Jmeter 在录制 HTTPS 的时候会在 bin 目录下生成临时根证书文件路径里有中文或者空格证书生成这一步直接失败界面上还只给你一句含糊的错误提示查半天查不出来。所以老老实实解压到D:\tools\apache-jmeter-5.6.3这种纯英文短路径下。第三个约束是环境变量。把 bin 目录加到 PATH 里同时配一个 JMETER_HOME 指向解压根目录。这样在任何目录下都能直接敲 jmeter 命令脚本和结果文件可以按项目分目录管理而不是全堆在 bin 里。配完环境变量记得重开一个终端窗口旧窗口读不到新变量这个低级问题我自己也犯过两次。# 进入解压目录的 bin 下启动图形界面仅用于录制和调试 cd /d D:\tools\apache-jmeter-5.6.3\bin jmeter.bat # Linux / macOS 下非 GUI 模式压测输出 jtl 结果并生成 HTML 报告 jmeter -n -t order.jmx -l order.jtl -e -o ./report2.2 语言、字体、内存与插件的初始化配置第一次打开 Jmeter界面是英文的菜单里 Options 下面有一项 Choose Language切成中文之后重启就生效。但更稳的做法是直接改配置文件因为 GUI 里切的语言有时候重启会丢。打开 bin 目录下的 jmeter.properties把语言和编码这两行配上。languagezh_CN sampleresult.default.encodingUTF-8 jmeter.save.saveservice.output_formatcsv jmeter.save.saveservice.response_datafalse jmeter.save.saveservice.samplerDatafalse后面两行是压测阶段的重点。结果文件默认会把每个请求的响应体和请求体都存下来压几百个并发的时候这个文件能涨到几个 G磁盘直接写满压测机先趴下。所以正式压测前一定要把这两项关掉只在调试期临时开。字体小这个问题也很烦人尤其是脚本里有中文的时候看着费劲。Jmeter 的界面字体受外观主题影响可以在 Options 里换 Look and Feel或者改 jmeter.properties 里的界面字体相关参数。另外脚本编辑区的字体是通过jsyntaxtextarea.font.size这类参数控制的改成 16 或者 18 舒服很多长时间盯着脚本眼睛能少受点罪。内存参数是压测机的命门。Windows 下编辑 jmeter.batLinux 下编辑 jmeter 脚本找到设置堆大小的那一行把默认值调大。默认往往只有 1G做几百并发的压测几个来回就 OutOfMemoryError。我一般按压测机物理内存的一半来配比如 16G 内存的机器给到 8G同时把新生代比例适当调一下。改完记得用非 GUI 模式跑图形界面本身就吃内存正式压测时开界面等于白白浪费一半资源。插件管理器的安装也不能漏。把 jmeter-plugins-manager 的 jar 包丢进 lib/ext 目录重启 JmeterOptions 下面会多出一个 Plugins Manager。后面要用的 JSON 相关元件、性能指标图表、以及某些录制扩展导出脚本后需要的依赖都靠它装。装插件的时候有个小技巧先看插件列表里的更新时间选最近还在维护的版本老插件在新版 Jmeter 上经常加载失败。3. 方式一Badboy 录制法以及它为什么慢慢退场了3.1 从打开页面到导出 JMX 的完整流程Badboy 的定位很明确它是一个自带浏览器的录制工具免费、体积小、不需要额外配置代理和证书。操作流程简单到几乎没有学习成本。打开 Badboy 之后界面左边是请求树中间是页面预览顶部是地址栏和录制控制条。在地址栏输入被测系统的入口地址敲回车页面加载完成后点顶部那个红色的圆形录制按钮然后就像正常用户一样在页面里操作登录、点菜单、填表单、提交。所有操作都会被记录到左边的树形结构里。全部走完之后点停止按钮录制就结束了。接下来的关键一步是导出。在左侧请求树上右键或者从 File 菜单里找到 Export to Jmeter 这一项选择保存路径生成一个 .jmx 文件。这个文件可以直接被 Jmeter 打开打开后你会看到一串 HTTP Request 采样器顺序和你在页面上的操作顺序一致。速度确实快整套流程十分钟以内能搞定。Badboy 早期的口碑很好主要是因为它解决了手写太累的问题而且不需要折腾代理和证书。在它还活跃的年代很多性能测试教材里都把它作为首推的录制方案。它的请求树结构也让初学者很容易理解一个页面操作对应若干个 HTTP 请求这件事学习价值不低。3.2 内核老旧带来的三个典型失败场景问题出在它的浏览器内核上。Badboy 内置的是很老的 IE 内核而今天的前端工程大量使用现代框架页面的渲染和数据加载都依赖新的浏览器能力。这就导致三类典型的失败。第一类是页面白屏。访问一个用现代框架搭的后台系统地址栏回车之后页面一片空白什么都渲染不出来录制树上只有一条主文档请求。原因很简单内核太老脚本报错页面初始化直接挂掉自然也不会有后续的接口请求被录下来。第二类是异步请求丢失。有些页面看起来能显示但列表数据、下拉选项全是空的。这些数据是通过异步请求拉回来的老内核里这部分逻辑没跑通请求根本没发出去录出来的脚本自然缺了最关键的那几条。等你回放的时候会发现登录完之后就断了因为后面的接口压根没录到。第三类是 HTTPS 站点报错。目标系统用了 HTTPSBadboy 在握手阶段就失败页面加载不出来或者弹出一堆证书警告手点忽略之后页面还是有问题。所以结论很清楚Badboy 只适合那些还在用传统表单提交、没有复杂前端逻辑、并且是 HTTP 或者证书兼容性没问题的老系统。新项目我基本不用它同样的思路用浏览器扩展来做内核是现代的成功率完全不是一个量级。提示如果你手上的系统确实是老式 B/S 架构Badboy 录出来的脚本也别直接压。它会把每个请求的完整头信息抄下来包括一些跟会话绑定的字段回放时照样会失败该做的关联一步都不能省。4. 方式二自带代理录制HTTP(S) Test Script Recorder全流程4.1 代理录制的原理与录制器参数详解这是 Jmeter 官方提供的正统方案也是我在 Web 项目里用得最多的一种。原理说穿了不复杂Jmeter 在自己机器上启动一个 HTTP 代理服务器监听某个端口然后让浏览器的所有流量都从这个代理走。每一个流经代理的请求Jmeter 就把它转成一个 HTTP Request 采样器按顺序塞进指定的位置。配置入口在测试计划上右键Add 下面找 Non-Test Elements就能看到 HTTP(S) Test Script Recorder。加进来之后有几个参数必须逐项确认。端口是第一个。默认给的 8888 一般不会冲突但如果撞上了别的服务就换一个比如 8899。端口被占用的报错很直接启动的时候日志里会写地址已被使用换一个就好。目标控制器是第二个决定了录下来的采样器往哪里放。默认会放到录制器自己下面但我更习惯提前建好一个线程组然后把目标控制器指向那个线程组。这样录完之后结构清晰不用再手动搬一遍。分组策略是第三个也是最容易被忽略的一个。录制器会根据两个请求之间的间隔时间判断要不要新建一个分组常见的选项包括不分组、每组加一个分隔符、每组生成一个事务控制器等等。选每组生成事务控制器最实用因为它能按操作节奏把请求自动归成一个个事务块后面做事务响应时间统计的时候省事。这个间隔时间由 jmeter.properties 里的参数控制默认值偏短业务操作慢的时候会切得太碎可以适当调大一点一般一千到五千毫秒之间按你的操作节奏试。头部捕获和重定向选项是第四个。是否录制 HTTP 头信息、是否自动跟随重定向这两项要按目标系统的行为来定。如果系统内部有跳转建议让录制器跟随并把重定向后的请求也录下来否则脚本里会缺链路。4.2 HTTPS 根证书的生成、安装与信任链打通HTTPS 是这条路线上最大的一道坎也是百分之八十的人卡住的地方。原理其实很容易理解Jmeter 作为代理需要在中间解密流量才能看到请求内容而解密的前提是浏览器信任 Jmeter 的证书。所以 Jmeter 会自己生成一张临时根证书你需要把它装到浏览器或系统的信任列表里。点击录制器上的 Start 按钮之后Jmeter 的 bin 目录下会生成一个证书文件名字类似 ApacheJMeterTemporaryRootCA.crt。弹出的小窗口会提示你证书的有效期默认只有七天左右所以这个操作不是一次性的隔一段时间要重新生成和安装。安装到 Windows 系统的流程是双击这个 crt 文件选择安装证书存储位置选本地计算机下一步选择将所有的证书都放入下列存储浏览找到受信任的根证书颁发机构确认导入。中间会弹一个安全警告点确定就行。装完之后最好在证书管理器里搜一下确认能看到这张证书位置在受信任的根证书颁发机构下面。macOS 的流程不一样需要通过钥匙串访问。打开钥匙串访问把 crt 文件拖进系统钥匙串找到这张证书双击打开信任设置把使用此证书时改成始终信任。新版 macOS 对根证书的管理更严格改完可能需要输入密码确认。Firefox 是最特殊的一个它有自己的证书库不读系统证书。所以如果你用 Firefox 录制必须单独在 Firefox 的设置里找到隐私与安全往下拉到底部的证书管理选查看证书在证书颁发机构那一栏点导入把 crt 导进去并且勾选信任这一项用于标识网站。这一点很多人不知道装完系统证书之后用 Chrome 能录换 Firefox 就报证书错误问题就出在这。浏览器代理的配置有两种方式。一种是改系统代理Windows 在设置里找代理macOS 在网络的代理选项里配填上 127.0.0.1 和录制器的端口。另一种是用浏览器上的代理切换扩展配置更灵活可以一键开关。我个人更推荐后一种因为录完之后点一下就能关掉不容易忘。说到忘这是最经典的一个坑录完脚本忘了关代理然后关掉 Jmeter浏览器就再也上不了网了所有流量都往一个已经关闭的端口上撞。遇到这种情况不用慌把代理关掉或者改回直接连接就好了。4.3 过滤器配置把静态资源和第三方域名挡在门外不加过滤直接录结果一定是一堆垃圾。一个后台首页加载下来图片、样式、字体、图标字体、脚本文件加起来能有三四十个请求这些对压测来说毫无价值白白撑大脚本体积还会严重干扰你阅读请求序列。录制器里的 URL Patterns to Include 和 URL Patterns to Exclude 就是干这个的。Exclude 里用正则把静态资源的后缀统统挡掉常见写法是把图片、样式、脚本、字体、图标、源码映射这些扩展名全部列进去。这个正则写一次就能复用很久建议存下来。Include 那一栏通常用来限定只录目标域名。如果被测系统会调用很多第三方服务比如统计埋点、短信验证码、地图服务把这些域名排除掉非常关键。否则你录出来的脚本里会混进一堆外部请求回放的时候还要依赖外网压测结果会被这些无关链路污染。我的习惯是分两遍录。第一遍不加任何过滤全量录一遍然后打开请求树看看都经过了哪些域名把不认识的、跟业务无关的挑出来。第二遍加上过滤规则重新录这时候出来的脚本就干净多了。多花五分钟省后面两小时。4.4 录完之后的四步清理与初步关联录完的脚本别急着压先做四件事。第一步删冗余。把静态资源、埋点、心跳、favicon 这些跟业务无关的采样器全删掉。删的时候注意别把 Cookie 管理器和 HTTP 信息头管理器连带删了这两个是基础元件得留着。第二步理结构。按业务动作把采样器组织到事务控制器下面比如登录、浏览商品、加购、下单、支付各自成组。之后看聚合报告的时候就能按事务维度看响应时间比一个个采样器看有意义得多。第三步处理关联。这一步是最花时间的。脚本里所有会话相关的动态值比如登录后返回的令牌、会话标识、页面里藏着的校验字段录制下来的时候都是固定值回放必挂。需要加后置处理器去动态提取再用变量引用。第 7 节会专门讲提取器的用法和那个特别有名的防伪标记案例。第四步做初步参数化。把账号密码、商品编号这类会变的输入换成变量为后面接 CSV 数据文件做准备。这一步不做多线程跑起来所有用户都用同一个账号服务端要么串数据要么直接把并发锁死压出来的结果完全没有参考价值。注意录制期间不要同时开着别的抓包工具或者代理插件。两个代理抢同一个端口会失败更麻烦的是流量被另一个工具截走了Jmeter 这边录出来是空的你还以为是配置写错了。5. 方式三抓包导出 HAR / JMX移动端和复杂场景的主力5.1 什么时候该放弃浏览器代理改用抓包浏览器代理录制的边界在哪里在浏览器之外。一旦被测对象变成手机 App、桌面客户端或者小程序里的某些原生请求浏览器代理就使不上劲了因为流量根本不从浏览器走。这时候抓包工具就是必选项。还有一种情况是只需要录某个特定接口。比如你只想压一个查询接口但是触发它的页面会连带发几十个请求用代理录制再删筛选效率很低。用抓包工具可以精确地只挑那一条会话导出省事很多。第三种情况是团队已经在用抓包工具做接口测试抓包结果可以复用。这时候直接在已有的抓包流程上导出脚本比重新搭一套代理环境要顺畅。我最常用的一招其实是浏览器开发者工具。打开开发者工具的 Network 面板勾上只显示异步请求把业务操作走一遍然后在请求列表上右键选择保存所有内容为 HAR 格式。整个过程不需要装任何额外软件导出的 HAR 文件里包含了完整的请求头、请求体、响应信息是后续转换的原料。5.2 从 DevTools/Fiddler 到 JMX 的两条转换路径从抓包结果到可执行的 Jmeter 脚本有两条路。第一条路是用抓包工具直接导出 JMX。部分抓包工具在会话导出菜单里就提供了 Jmeter 脚本这一项选中你要的会话导出成 .jmx用 Jmeter 打开即可。这条路的好处是省掉了中间格式转换缺点是导出的脚本元件结构比较朴素头信息管理器、Cookie 管理器这些基础元件往往没有自动带上需要你打开之后手动补。第二条路是走 HAR 中转。抓包工具和开发者工具都能导出 HAR 格式然后借助转换工具把 HAR 转成 JMX。社区里有若干开源的转换工具有命令行的也有图形界面的用法基本都是输入 HAR 输出 JMX 这个套路选一个还在维护的版本就行。命令行工具的一般用法类似下面这样。# HAR 转 JMX 的命令行套路具体工具名按你选的那个来 java -jar har-to-jmx.jar -i capture.har -o script.jmx # 转换完用非 GUI 模式跑一遍冒烟看结构有没有问题 jmeter -n -t script.jmx -l smoke.jtl走 HAR 这条路有几个细节要注意。HAR 文件会把每个请求的响应体也塞进去一个完整的业务流程 HAR 可能有几十上百兆转换过程会很慢。所以导出前先在开发者工具里用筛选条件只留下你要的请求类型能小一个数量级。另外 HAR 里记录了每个请求的耗时转换工具有时候会把这些耗时翻译成定时器压测的时候会拖慢整个脚本转换完记得检查并清掉。5.3 手机 App 抓包的操作顺序与合规边界手机端抓包的顺序固定一步一步来基本不会出问题。手机和电脑连同一个无线网络确认两边在同一个网段能互相访问。在电脑上启动录制器或者抓包工具看清它的监听端口。然后在手机的无线网络设置里把当前这个网络改成手动代理主机名填电脑的局域网地址端口填工具监听的端口。保存之后打开 App 走业务流程电脑这边就能看到请求。证书这一关躲不掉。手机浏览器访问代理地址下载并安装根证书安卓系统需要在安全设置里手动安装到用户证书部分高版本系统还需要在应用层面允许用户证书iOS 则要在设置里安装描述文件之后再手动开启完全信任。这几步任何一步漏了看到的就全是加密流量只有连接记录没有内容。这里必须说清楚一条边界。如果 App 对证书做了绑定代理方式拿到的流量会直接中断请求发不出去。遇到这种情况正规做法是找开发同学要一个测试包或者直接要接口文档自己手写而不是去折腾各种绕过手段。压测的目的是验证自己系统的承载能力不是在突破安全机制走正门最快也最安全。6. 方式四浏览器扩展录制五分钟出脚本的快路子6.1 扩展录制的工作机制与天然优势浏览器扩展录制的原理跟前三种都不一样。它不去架代理、不去解流量而是直接读浏览器自己的网络事件。扩展在浏览器里跑浏览器发出什么请求它就知道什么请求把它记成一条条步骤最后导出成 JMX。这个过程天然绕开了证书和代理这两个大麻烦因为流量根本没被截走走的还是浏览器自己的安全通道。这个特性带来三个明显的好处。第一是零配置装完扩展点一下录制就能开工对刚接触性能测试的人来说心理门槛低很多。第二是 HTTPS 无痛不用装根证书、不用配代理也不会有忘关代理然后上不了网的问题。第三是操作直观扩展界面上一边操作一边能看到已经被记录的请求列表录错了当场就能发现。但它也有明确的短板。扩展只能看到浏览器发的流量手机上运行的原生应用、桌面客户端、后台服务之间的调用它一概看不见。另外某些单页应用的请求是在页面生命周期里大量异步发出的扩展可能只记录到一部分或者把发起顺序记乱了。还有一个隐性问题扩展录制的是浏览器视角的请求有些 Cookie 和头信息是浏览器自动补的导出的脚本里不一定带回放的时候可能因为缺少会话信息而失败。6.2 导出的 JMX 打不开兼容性问题的处理用扩展录出来的脚本最常见的报错是打开的时候提示找不到某个类。原因很简单这类扩展通常自带一套元件实现导出的 JMX 里引用了它们自己的组件类而你的 Jmeter 里没有这些类。解决办法有两条。一条是补依赖。用插件管理器搜索并安装扩展所依赖的插件包装完重启 Jmeter报错就消失了。大多数主流录制扩展都会在导出页面或者文档里说明需要哪些插件按图索骥就行。另一条是清理引用。如果实在找不到对应插件或者那个插件已经停止维护了可以另存一份脚本备份然后用文本编辑器打开 JMX 文件搜索里面引用到的类名把不认识的元件连同它的配置一起删掉只保留标准的 HTTP Request 采样器和控制器。这个操作有点糙但保住主要请求链条是没问题的实测下来能救回八九成的脚本。还有一个更省事的做法导出的脚本只当草稿用把所有请求结构复制到一个自己新建的干净测试计划里重新挂上标准的 HTTP 信息头管理器、HTTP Cookie 管理器、CSV 数据文件设置。这样结构干净也不会带着别人家的依赖后面维护起来省心。7. 录制只是骨架把脚本改造成真正能扛压的脚本7.1 参数化CSV 分配模式与 CSV/JDBC 数据源的用法录制出来的脚本输入值全是写死的。多线程一跑所有线程拿同一个账号登录、查同一个订单服务端要么直接把你踢掉要么数据串成一片压出来的数字毫无意义。参数化就是把写死的值变成可替换的变量。最常用的是 CSV 数据文件设置。配置项里几个字段必须搞明白。文件名填相对或绝对路径编码一定要写 UTF-8不然中文数据读进去是乱码。变量名是按列顺序用逗号分隔的多个变量对应多列。分隔符默认是逗号如果你的数据里有逗号记得换一个分隔符或者勾上允许带引号的数据。真正决定行为的是最后两个选项文件读到结尾之后是否循环、以及是否停止线程还有那个共享模式下拉框。这三项的组合决定了数据怎么分到各个线程手里。共享模式行为适用场景所有线程共享所有线程共用一个文件指针每个线程每轮取到不同的行唯一账号登录一个账号只用一次当前线程组每个线程组内部共享一个指针多线程组并行压不同业务每个线程独立每个线程各自从头开始读文件每线程固定绑定一套账号如果你想要同一个 CSV 文件里每个线程分块取值本质上是想让各线程拿到的数据互不重复。实现方式是选所有线程共享同时把读完是否循环关掉、读到头是否停止线程打开这样文件从头到尾被消费一遍线程之间自然不重叠。如果数据量不够还不如按线程拆成多个文件用线程号拼文件路径每个线程读自己那份边界最清楚。数据库取值是另一条常见路子。用 JDBC 连接配置建好连接然后用 JDBC 请求元件执行查询查询结果会自动按列生成变量引用的时候加上索引比如第一行第一列就是变量名加下划线加一。想让查询出来的数据作为下一个接口的入参有两种常见做法一种是在后续请求里直接引用带索引的变量针对固定行另一种是配合循环控制器遍历整个结果集把每行都跑一遍。后一种更适合批量场景。-- JDBC 请求里的查询语句变量名填 orderId,orderNo对应两列 SELECT id AS orderId, order_no AS orderNo FROM t_order WHERE status 0 LIMIT 100;配置 JDBC 连接的时候有个容易忘的点数据库驱动 jar 包要放到 lib 目录下放完重启 Jmeter。连接串、用户名、密码建议用变量引用不要把生产密码明文写在脚本里脚本是要提交到版本库的。7.2 关联正则、JSON 提取与防伪标记的经典案例关联解决的是上一个请求的响应里有下一个请求需要的值这个问题。做法是在产生这个值的采样器下面挂一个后置处理器把值提取出来存成变量后面的请求用变量引用。提取器有两类最常用。一类是正则表达式提取器靠引用名称、正则表达式、模板、匹配数字这几个字段工作万能但对嵌套结构不友好。另一类是 JSON 提取器直接按 JSON 路径表达式取值写起来简洁前提是响应确实是 JSON。能用 JSON 提取器就别用正则出错的概率低很多。这里说一个特别有代表性的坑。有些基于老式 Web 框架的系统表单提交的时候会带一个防伪标记字段页面上以隐藏输入框的形式存在值每次刷新都变。你用录制的方式把这个值抄下来回放的时候服务端一校验直接返回未提供必要的防伪标记接口 500 或者 400。这个问题的本质就是典型的关联缺失。解决办法是三步。第一步在打开表单页的请求下面加一个提取器用 XPath 或者正则把这个隐藏输入框的 value 取出来存成变量。第二步在提交表单的请求里把原来写死的值改成变量引用。第三步确认 Cookie 管理器是开着的因为一般还会有一个会话 Cookie 需要一起带上。签名类参数是关联的另一个极端。有些接口的请求参数里带时间戳和签名签名是密钥加时间戳拼起来算的哈希。这种值没法从响应里提取必须用脚本预处理器现场算。做法是在请求上加一个 JSR223 预处理器用 Groovy 算出签名塞进变量里。如果签名算法特别复杂还有一个很实际的办法找开发同学在测试环境把签名校验开关关掉。压测的目的是测承载能力不是测签名算法能在测试环境省掉的校验就别硬啃。// JSR223 预处理器示例拼一个带时间戳的签名变量 def ts System.currentTimeMillis().toString() def raw appKeydemots ts secrettestsecret def sign raw.encodeAsMD5() // 按实际接口的算法替换 vars.put(ts, ts) vars.put(sign, sign)7.3 断言、事务控制器与定时器让压测结果站得住没有断言的压测是假压测。默认情况下Jmeter 只看 HTTP 状态码返回 200 就算成功。可很多系统出错的时候也返回 200错误信息藏在响应体里。这种情况下你压出来的成功率百分之百实际业务全线失败报告拿出去是要出事的。断言要分层加。最外层加一个响应断言检查响应里是否包含成功标识再往细里加 JSON 断言按字段判断业务码。如果判断逻辑比较复杂就用 JSR223 断言写脚本判断灵活性最高。// JSR223 断言示例按业务码判断请求是否真的成功 def resp prev.getResponseDataAsString() def json new groovy.json.JsonSlurper().parseText(resp) if (json.code ! 0) { prev.setSuccessful(false) prev.setResponseMessage(业务码异常: json.code) }事务控制器是把一组采样器的耗时合并成一个事务指标显示的元件。勾上生成父采样器之后报告里就能看到下单这个动作端到端的响应时间而不是分散在七八个接口上。还有一个细节是否把定时器和前后置处理器的耗时算进事务这个选项要按你的统计口径来选跟团队说清楚否则同一份报告不同人算出来的数不一样。定时器决定了压测的形态。想模拟真实用户就在请求之间加一个随机等待模拟人的思考间隔。想按固定吞吐量加压就用恒定吞吐量定时器设定每分钟的请求数目标Jmeter 会自动调节请求间隔去逼近这个目标。这是做阶梯加压和容量摸底时最有用的一个元件。定时器的作用域要注意放在线程组下面它会影响组内所有采样器放在某个采样器下面只影响那一个。最后是结果收集。察看结果树在调试期很有用可以看到每个请求的完整请求响应内容但它非常吃内存正式压测时必须关掉。压测用非 GUI 模式输出结果文件再用命令生成网页版报告。如果确实需要从结果树里导出某段数据排查问题用界面上的保存表格数据功能导出成 CSV但别在整个压测过程中一直开着这个监听器。8. 录制与加压阶段的高频问题速查8.1 录制阶段证书、空脚本、代理失效录制环节的问题集中度高基本就那几个整理成表随时翻。现象常见原因处理办法开录之后浏览器打不开任何网页代理指向了没启动的端口或 Jmeter 已关闭关掉浏览器代理重启录制器再开代理页面能开但录不到内容只录到一条连接请求证书没被信任重新生成根证书并安装到系统或浏览器证书库用 Firefox 录 HTTPS 报证书错误Firefox 有独立证书库不读系统证书在 Firefox 证书管理里单独导入并设为信任录出来的脚本全是图片和样式过滤规则没配在排除规则里按后缀正则挡掉静态资源脚本里混了一堆外部域名请求埋点、统计、第三方服务被一起录了把这些域名加进排除规则或者录完手动删除回放全部失败提示会话失效动态值没做关联或缺 Cookie 管理器加提取器动态取值补上 Cookie 管理器表单提交报缺少校验标记页面里的隐藏校验字段是动态生成的从表单页响应中用提取器取值提交时引用变量bin 目录里找不到证书文件解压路径含中文、空格或无写权限换成纯英文短路径重新解压手机端抓到的全是加密流量证书没装到用户证书或未开启完全信任按系统要求安装描述文件并开启信任开关还有一条不算问题但容易被忽略的经验录制环境要尽量贴近真实。用测试环境的数据和账号走完整的业务链路别图省事跳步骤。录的时候少走一步压测的时候就少覆盖一个接口最后报告里的容量数字就是虚的。8.2 加压阶段报错、端口耗尽与压测机瓶颈录好脚本、调好参数正式加压的时候还有一波坑在等你。这些坑跟录制本身没关系但每一步都在消耗你的时间所以一并列出来。现象常见原因处理办法大量请求报写入服务器失败服务端主动断连或上传文件过大或连接被限流降并发压测定位临界点调大超时检查网关连接数限制请求报连接被重置中间层并发保护或长短连接不匹配调整连接复用策略与服务端配置对齐内存溢出结果树开着或堆内存太小关监听器调大堆用非 GUI 模式跑压测机端口不够用短连接太多本机动态端口被耗尽开启连接复用调整系统连接参数增加压测机压测机 CPU 或网卡先打满压力发不出去瓶颈在客户端用系统监控确认把压力分散到多台机器并发加不上去TPS 卡在低位定时器限制、重定向过多、或有同步等待检查定时器作用域排查重定向和阻塞点结果文件几十个 G把响应数据一起存了关闭响应数据保存只留统计字段结果树导出卡死边压边用界面导出用非 GUI 模式输出结果文件事后生成报告关于写入服务器失败这一类报错我的排查顺序是固定的先降并发把线程数压到很低再跑一遍如果低并发正常那就是承载问题如果低并发也报就是脚本或协议层面的问题去检查是不是请求体太大、是不是缺少必要的头、是不是服务端对某个接口有特殊限制。这个二分法能快速把问题圈定在容量还是脚本这两个大类里比盲目改参数高效得多。分布式的思路也值得早一点考虑。单台压测机的并发能力其实很有限几千并发往往就已经被本机端口和网络带宽卡住了。早期就用多台压力机做分布式能避免以为是服务端扛不住结果是压测机先趴了这种误判。用命令行模式启动从节点和控制节点把线程数分摊下去结果汇总到一个文件里分析这是做高并发验证的标准姿势。我个人在实际操作中的体会是录制这件事真正的价值不在录而在录完之后你被迫去理解整个业务链路。你得一层层剥开请求看清楚哪一步在传会话、哪一步在算签名、哪一步的结果被下一步消费这个过程中你对系统的理解会远超写脚本本身。所以别把录制当捷径把它当一次把系统调用链画清楚的机会压测报告的每一个数字才站得住脚。