JMeter基础用法

JMeter启动模式

JMeter 的 bin 目录下提供了多个启动脚本,它们的功能和适用场景有明显区别,主要可以分为 GUI 模式CLI 模式(命令行非 GUI)分布式/服务器模式远程控制 四类。


一、GUI 模式相关(编写、调试脚本)

脚本 关键区别 使用场景
jmeter.bat 启动 带 Windows 命令行窗口 的 GUI。控制台会同步输出日志,关闭窗口则 GUI 一并退出。 在编写、调试测试计划时使用,方便直接看到后台日志和异常信息。
jmeterw.cmd 启动 不带命令行窗口 的 GUI,日志只会写入 jmeter.log,关闭窗口不会因误关控制台而中断 JMeter。 当你只想打开 JMeter 界面、不希望被黑色控制台窗口干扰时使用。
jmeter-t.cmd 拖放一个 .jmx 文件到该脚本上,会用 GUI 模式直接打开这个测试计划,免去手动 File → Open。 快速加载已有测试脚本进行查看或编辑。

二、CLI 模式相关(正式执行压力测试)

脚本 关键区别 使用场景
jmeter-n.cmd 非 GUI 命令行模式 ,拖放 .jmx 文件后以 CLI 模式执行,可附加 -l-e-o 等参数生成报告。 所有正式压测都必须使用此模式,资源消耗低、无界面渲染开销,结果更准确。
jmeter-n-r.cmd 也是 CLI 模式,但会 远程执行(-r 参数),将测试分发到已配置的远程 JMeter 服务器上。 需要多台机器产生并发负载的分布式压测场景。需提前在各负载机上启动 jmeter-server

三、分布式 / 服务器组件

脚本 关键区别 使用场景
jmeter-server.bat 启动 JMeter 服务器模式,等待控制端(master)发来的测试任务并在本地执行。 分布式压测中 所有负载生成机(slave) 上必须运行此脚本,使它们能被主控机调用。
mirror-server.cmd 启动 镜像服务器,它会将收到的 HTTP 请求原样返回。用于验证 JMeter 发出的请求内容是否正确。 调试 HTTP 取样器、检查请求头和 body 是否按预期构造,不用于真实压力测试。

四、远程控制(停止正在运行的测试)

脚本 关键区别 使用场景
shutdown.cmd 向运行中的 CLI 实例发送 优雅停止 信号,会等待当前正在执行的采样器完成后再结束线程。 需要让压测"体面"地收尾,收集完进行中的请求数据,不丢失最后的统计。
stoptest.cmd 向运行中的 CLI 实例发送 立即停止 信号,所有线程立刻终止,不等待当前请求完成。 测试发现问题需要紧急终止,或不想等待正在执行的慢请求时使用。

一句话总结

  • 编辑调试用 jmeter.batjmeter-t.cmd
  • 正式压测一律用 jmeter-n.cmd(单机)或 jmeter-n-r.cmd + jmeter-server.bat(分布式);
  • 调试 HTTP 请求可用 mirror-server.cmd
  • 远程优雅停止用 shutdown.cmd,紧急停止用 stoptest.cmd

JMeter 的测试原理基于多线程并发模拟用户请求,核心工作流程围绕"创建测试计划 → 配置虚拟用户行为 → 执行并发负载 → 收集与呈现结果"展开。


一、测试原理

1. 线程模型:虚拟用户

  • JMeter 使用 线程组 来模拟并发用户,每个线程即一个虚拟用户。
  • 线程组内可设置:线程数(并发量)、Ramp-Up 时间(启动间隔)、循环次数/持续时间
  • 所有线程彼此独立,按测试计划中的采样器顺序执行请求,完全隔离,不共享状态(除非使用了变量/属性跨线程传递)。

2. 核心组件协作

  • 采样器:负责发送具体协议请求(HTTP、JDBC、FTP、JMS 等),记录响应时间、状态、数据大小等。
  • 逻辑控制器:控制请求执行顺序(循环、条件、事务等),定义用户行为流。
  • 断言:对响应内容做校验(文本、状态码、JSON 路径等),用于功能正确性判定,不影响负载生成。
  • 前置/后置处理器:在请求前后做数据处理,如提取变量(正则、JSON 提取器)、生成参数。
  • 定时器:模拟真实用户思考时间或固定请求间隔,控制吞吐节奏。
  • 配置元件:如 HTTP 请求默认值、CSV 数据源(参数化),供采样器复用。
  • 监听器:收集和展示测试数据(聚合报告、图形),可在运行时或结束后分析。

3. 执行引擎

  • JMeter 引擎本身不渲染 GUI 响应(如浏览器不会执行 JavaScript),而是 纯协议层负载生成器
  • 它直接构造原始请求并发送,接收响应字节,测量网络往返时间,不解析页面中的静态资源 除非手动添加对应采样器。
  • 压力机资源消耗主要来自网络 I/O 和线程调度,因此 CLI 模式(jmeter-n.cmd)能最大化压测能力。

4. 分布式原理

  • 支持 Master-Slave 架构:一台控制机分发测试脚本,多台负载机同时执行。
  • Slave 上运行 jmeter-server,接收 Master 发送的测试计划片段,按独立线程组生成负载并回传结果给 Master 汇总。
  • 通信通过 RMI(Java 远程方法调用)完成,可突破单机线程数上限。

二、测试流程

一个完整的 JMeter 压测流程分为 7 个关键步骤:

1. 需求分析与场景设计

明确目标:并发数、吞吐量(TPS/QPS)、响应时间要求、测试时长、协议类型。

确定业务场景:哪些接口?比例如何?是否需要参数化、依赖关系处理等。

2. 创建测试计划

打开 JMeter GUI,整个 .jmx 文件就是一个测试计划。

→ 右键测试计划 添加 → Threads (Users) → 线程组

3. 配置线程组(并发策略)

设置:

  • 线程数:模拟的用户数量
  • Ramp-Up 期:所有线程的启动耗时(避免瞬间冲击)
  • 循环次数 / 持续时间:控制压测时长,推荐使用"调度器------持续时间"

4. 添加配置元件与采样器

  • 配置元件:HTTP 请求默认值(协议、服务器 IP、端口),CSV 数据文件(登录多账号)。
  • 采样器:HTTP 请求、JDBC 请求等,填写路径、方法、参数、消息体。
  • 后置处理器 (关联):提取 tokensessionID 供后续请求使用。
  • 定时器:如高斯随机定时器,模拟用户阅读/填写等待。

5. 添加断言与监听器(验证与分析)

  • 断言:返回码 200、包含特定文字,判断业务是否正确。
  • 监听器 :常用 聚合报告查看结果树 (调试时)、后端监听器(实时推送到 InfluxDB + Grafana)。

⚠️ 调试阶段可保留监听器,正式压测时务必禁用或移除所有监听器(尤其"查看结果树"),否则极大消耗负载机资源并扭曲结果。

6. 执行测试

  • 调试:用少量线程 + 查看结果树,确认请求正确、断言通过。
  • 正式压测 :必须使用 CLI 模式执行(jmeter-n.cmd -t 脚本.jmx -l 结果.jtl -e -o 报告目录)。
    常用命令参数:
    • -n:非 GUI 模式
    • -t:指定测试计划文件
    • -l:记录结果到 JTL 文件
    • -e -o:生成 HTML 报告

7. 结果分析与报告

  • 聚合报告中关注:Average(平均响应时间)、Median、90/95/99 百分位、Error%、Throughput
  • HTML 报告会展示图表:响应时间分布、每秒事务数、活跃线程数等。
  • 结合服务器资源监控(CPU、内存、IO、网络)定位瓶颈。

流程图简览

复制代码
需求分析 → 编写脚本(GUI调试) → CLI执行 → 监控与结果收集 → 分析调优
   ↑                                    ↓
   └──────── 发现问题后重新修改脚本 ←──────┘

核心原则 :GUI 仅用于开发调试,所有正式负载测试务必使用 CLI 模式,才能保证压测结果准确、可复现。


实践

一、HTTP 协议层面的最小请求

  • GET 请求

    • 请求行:GET / HTTP/1.1
    • 唯一必需的请求头:Host
    • 没有请求体。
  • POST 请求

    • 请求行:POST / HTTP/1.1
    • 必需请求头:
      • Host
      • X-Csrftoken(值=csrf_token)
      • Cookie(含sessioncsrf_token)
    • 特殊的请求头:(部份产品要求)
      • Referer(且值必须是完整的https://...)
      • User-Agent
    • 一般框架自动处理,无需主动添加:
      • 如果有请求体,必须加 Content-Length (值为字节数);若无请求体,可带 Content-Length: 0
      • 理论上可没有 Content-Type,但服务器通常需要它来解析请求体,所以实际中它也是必需的。

二、参数化

1、用户定义变量 + ForEach 控制器

适用场景:数据量较少、逻辑简单、无需外部文件的小规模变量列表遍历,例如固定几个 ID 轮流使用。

配置步骤与关键点

  1. 定义变量列表

    • 位置 :测试计划 → 添加 → 配置元件 → 用户定义的变量(User Defined Variables)。
    • 编辑 :手动添加一系列命名规律、后缀连续的变量,如:
      • id_1 = 1001
      • id_2 = 1002
      • id_3 = 1003
    • 注意 :变量名前缀和后缀数字必须连续,且需额外定义一个变量(如 id_count = 3)记录总个数,供 ForEach 控制器使用。
  2. 使用 ForEach 控制器遍历

    • 位置 :线程组 → 添加 → 逻辑控制器 → ForEach 控制器
    • 编辑参数
      • 输入变量前缀:填 id(与定义时的前缀一致,不含下划线)。
      • 开始索引1(从 id_1 开始)。
      • 结束索引id_count 对应变量的值,此处可填变量 ${id_count}(由用户定义变量中设置)。
      • 输出变量名称currentId,后续请求通过 ${currentId} 引用当前循环到的值。
    • 结构:将需要参数化的请求放入 ForEach 控制器内。
    • 注意:ForEach 会在一次迭代内顺序走完所有变量,要让它与线程循环配合,可在外层加线程组循环次数,或在 ForEach 内再用循环控制器控制迭代。

2、CSV 数据文件设置(CSV Data Set Config)

适用场景:参数数据量大、需用 Excel/文本文件管理、不同用户使用完全不同数据的并发场景(最常用)。

配置步骤与关键点

  1. 准备 CSV 文件

    • 文件内容:第一行为变量名可省略(通过配置指定变量名则不读取第一行),每行一条数据,列用分隔符(默认逗号)分开。

    • 示例:users.csv

      复制代码
      user1,pass1
      user2,pass2
      user3,pass3
    • 编码建议 UTF-8,文件放于 JMeter 启动目录或测试计划同目录。

  2. 添加 CSV Data Set Config

    • 位置 :线程组或具体请求下 → 添加 → 配置元件 → CSV Data Set Config
    • 关键参数编辑
      • Filename:文件路径(相对路径以 JMeter 启动目录为基准)。
      • File EncodingUTF-8(避免乱码)。
      • Variable Names:逗号分隔的变量名,如 username,password(必须与文件列顺序一致)。
      • 忽略首行:如果文件第一行是标题则设为 True,否则 False
      • 分隔符:默认为逗号,若文件是 Tab 分隔则填入 \t
      • 是否允许带引号:数据包含引号时按需设置 True
      • 并发控制相关
        • 线程共享模式
          • 所有线程:所有虚拟用户按文件顺序共同消费数据,每个用户取一条新记录,适合"数据不重复"场景。
          • 当前线程组:每个线程组独立读取,组内线程共享。
          • 当前线程:每个线程独自从头读取文件,数据可重复。
      • 遇到文件结束符再次循环?(Recycle on EOF)
        • True:读到文件尾后重新从头开始循环读取。
        • False:读到文件尾后停止,此时 遇到文件结束符停止线程?(Stop thread on EOF) 生效。
      • 遇到文件结束符停止线程?(Stop thread on EOF)
        • True:文件结束且不循环时,停止当前线程。
        • False:文件结束后变量值变为 <EOF> 或保持最后一行,需注意处理。
    • 引用变量 :在请求参数中使用 ${username}${password} 即可。

典型并发配置示例

  • 唯一数据、不重复、用完即止共享模式 = 所有线程,Recycle = False,Stop thread on EOF = True,数据量 > 并发用户数 × 循环次数。
  • 数据可重复、压力持续共享模式 = 所有线程,Recycle = True,Stop thread on EOF = False。

总结:

  • 少量固定数据、简单循环 → 用户定义变量 + ForEach 控制器。
  • 大量、外部管理、真实用户模拟 → CSV Data Set Config。

三、依赖数据提取&使用

添加后置处理器,提取参数 存到变量中:

通过变量访问前置响应中的数据:${变量名称}

还可以添加IF控制器,比如:判断市场订单获取成功,才继续购买拉取收银台等后续接口的请求:${__groovy(vars.get("sell_order_id")!=null,)}

最终的结构如下:


四、修改响应参数

对提取出的值进行计算再使用,最推荐的方式是 JSR223 后置处理器/前置处理器(语言选 Groovy)

  1. 在 JSON 提取器同级或之下添加 JSR223 PostProcessor

    • 右键取样器 → 添加 → 后置处理器 → JSR223 PostProcessor。
  2. 编辑参数

    • Language :选择 groovy

    • Parameters:留空或传入需计算的变量名(非必须)。

    • Script :写入计算逻辑,并用 vars.put("新变量名", 计算结果) 保存。

      groovy 复制代码
      // 获取原始值
      String raw = vars.get("raw_token")
      // 进行计算(例如 Base64 编码)
      String encoded = raw.bytes.encodeBase64().toString()
      // 存入新变量
      vars.put("encoded_token", encoded)
  3. 在后续请求中引用 ${encoded_token} 即可。


五、测试活动与测试片段

测试片段

测试片段的关键决策点,在于你是否需要"重复执行同一段复杂逻辑"。

1. 需要多次复用的"原子业务块"

场景 :测试计划中有"领取优惠券 -> 下单 -> 支付"和"领取优惠券 -> 过期退款"两条流程。每个虚拟用户都要用自己的账号领取不同的优惠券。

  • 不用片段:你得在两个线程组里,把领取优惠券的整套请求(查询可用券、领取、校验状态)各复制一份。一旦接口变更,你要改两处。
  • 用测试片段 :把"领取优惠券"封装成片段,在两个线程组里用模块控制器调用。修改片段即全局生效,代码零重复。setUp 线程组做不到这一点,因为它只执行一次。

2. 需要封装"多步骤、多控制器、多断言"的黑盒组件

场景:一个"安全校验"流程,内部包含 3 个请求,并有多个 If 控制器判断异常,还有响应断言。

  • 不用片段:把这一大堆元件到处复制,脚本臃肿难读。
  • 用测试片段:这个复杂的逻辑块对外只暴露一个"模块名",调用方不用关心内部细节。setUp 线程组可以执行它,但无法让它在不同的执行分支里被"随地调用"。

3. 需要跨脚本/跨团队复用的独立物理文件

场景 :多个 .jmx 脚本都要用到同一个复杂的加密签名逻辑。

  • 不用片段:你只能每次都在新脚本里重建一堆请求和脚本,或者复制粘贴。
  • 用测试片段 :把加密逻辑存为 encrypt_fragment.jmx,其他脚本通过 Include 控制器 引用。实现团队级别的模块库。

测试活动

测试活动可以精准控制当前线程的行为,主要有三种用法:

  • 暂停 (Pause) :定时器通常作用于一个范围,而测试活动可以像"钉子"一样,在请求A和B之间插入一个一次性的定点等待。比如你在之前的案例里,用于登录后查询前的固定等待。

  • 停止线程 (Stop / Stop Now) :这是它更关键的功能。你可以把它放在 If 控制器 里,实现"条件停止"。

    • 典型场景就是刚才的案例:当检测到登录失败(token为空),就用"Stop"让这个虚拟用户优雅退出,避免后续请求全报错,污染测试报告。这与通过后置处理器抛错不同,它能直接终止线程的生命周期。
  • 继续 (Continue) :它可以放在 ForEach 控制器循环控制器 内部,结合条件判断,用来跳过某次循环 ,就像编程里的 continue 语句。

简单总结一下使用时机:

  • 何时用暂停 :在请求A和B之间必须有一个固定间隔,且不想影响其他请求时使用。
  • 何时用停止 :在遇到无法恢复的错误(如登录失败、用户余额不足等)时,配合 If 控制器来主动终止该线程。
  • 何时用继续 :在遍历循环(如 ForEach)中,需要根据条件跳过当前这一项,直接处理下一个时使用。

下面用一个 API 查询场景 串联"测试片段"和"测试活动",让你理解它们的实际用法。

测试目标:查询用户订单列表的接口 /api/orders,该接口必须先登录获取 token

要求:

  • 登录逻辑(请求 + 提取 token)需要被多个线程组复用
  • 获取 token 后,模拟用户思考 2 秒再查订单。
  • 如果登录失败(token 为空),立刻停止当前虚拟用户,避免后续无效请求。

步骤一:用"测试片段"封装可复用的登录模块

1. 创建测试片段

  • 右键测试计划 → 添加测试片段测试片段
  • 名称改为 登录模块

2. 在片段内添加元件

登录模块 下添加:

① HTTP 请求(登录接口)

  • 协议、服务器、端口、方法(POST)、路径填 /api/login
  • Body Data 填写 {"username":"test","password":"123456"}(后续可参数化)。

② JSON 提取器

  • 变量名:token
  • JSON Path:$.data.access_token
  • Match No.:1
  • 默认值:NOT_FOUND

这个片段现在就是一个独立的、可被调用的模块,但它本身不会执行。


步骤二:主测试计划引用片段,并用"测试活动"控制流程

1. 添加线程组

  • 线程数:1(便于观察,实测可加大)。
  • Ramp-Up:1
  • 循环次数:1

2. 引用登录片段

  • 右键线程组 → 添加逻辑控制器模块控制器
  • 在模块控制器中,Module to Run 选择刚创建的 登录模块

此时,模块控制器执行时会运行片段内的所有元件,即发送登录请求并提取 token

3. 根据 token 结果决定是否停止线程

我们希望:如果 token 为 NOT_FOUND(登录失败),则停止该线程,不再执行后续查询

  • 右键线程组 → 添加逻辑控制器如果(If)控制器
  • 条件:"${token}" == "NOT_FOUND" (勾选"Interpret Condition as Variable Expression?")。
  • 在 If 控制器下添加 取样器 → 测试活动 ,配置:
    • 目标当前线程(只停当前用户)。
    • 动作停止(优雅停止,完成本次迭代后不再继续)。
    • 持续时间留空。

这样,当 token 提取失败时,测试活动会让当前线程停止,后续的查询请求就不会执行了。

4. 模拟思考时间后再查询

如果 token 正常(即 If 条件不成立),我们希望延迟 2 秒再发查询请求(模拟用户浏览)。

  • 右键线程组 → 添加取样器测试活动(另一个)。
  • 配置:
    • 目标当前线程
    • 动作暂停
    • 持续时间2000(毫秒)。
  • 将这个测试活动直接放在查询请求的前面(不用 If 包裹)。

5. 添加查询请求

  • 右键线程组 → 添加取样器HTTP 请求
  • 路径:/api/orders
  • 在 HTTP 头管理器中添加 Authorization: Bearer ${token}

整个结构如下:

复制代码
线程组
├── 模块控制器(→ 登录模块)
├── If 控制器(token == "NOT_FOUND")
│   └── 测试活动(停止)
├── 测试活动(暂停 2000ms)
└── HTTP 请求(/api/orders)

执行效果:

  • 测试片段:登录请求和 token 提取被复用,当有多个线程组都要登录时,只需再添加模块控制器引用即可,不用复制粘贴。
  • 测试活动(停止):当 token 未提取成功时,优雅终止当前线程,避免后续请求因缺少 token 而大量报错,保持测试结果干净。
  • 测试活动(暂停):在查询前定点插入 2 秒等待,模拟真实用户操作间隔,而且不依赖于定时器(定时器会影响作用域内所有请求,而测试活动只在这里停一次)。

六:总结

JMeter 的核心角色是"负载生成器"和"客户端性能数据采集器",它能告诉你的是:

  • 并发压力下,从用户端看,响应有多快、成功与否、吞吐量有多大
  • 但它无法直接告诉你"为什么慢",因为服务器内部的线程、CPU、内存、锁、SQL 执行计划等信息,JMeter 是完全看不到的。

因此,JMeter 的定位就是:

发现问题 + 量化现象,而不是根因定位。

相关推荐
查拉图斯特拉面条1 天前
【JMeter 高阶】正则提取器万能匹配 gsdm、czygsdm、ddgsdm 同后缀字段
jmeter
原来是猿1 天前
安装JMeter
jmeter
查拉图斯特拉面条1 天前
JMeter 兼容整数 / 小数金额断言方案:JSONPath 转为 JSR223 Groovy 断言实战
jmeter
1candobetter2 天前
JMeter 常见功能在调试阶段与正式压测阶段的使用建议
jmeter·压力测试
Demon1_Coder2 天前
微服务-jmeter
jmeter
BullSmall3 天前
JMeter AI 插件
人工智能·jmeter
BullSmall3 天前
JMeter插件变灰?3步解决FeatherWand问题
jmeter
海的透彻4 天前
jmeter预制处理器JSR223-加解密
开发语言·jmeter·sm2·jsr233
oh-pinpin4 天前
【jmeter】-脚本-文件上传接口实现
jmeter