AI训练吞吐基准测试平台搭建实战 - 第3节

线程组与取样器:压测脚本的起点

说实话,很多新手拿到JMeter第一件事就是加线程组、配取样器,然后直接跑。嗯,我当年也这么干过。结果呢?压测数据一塌糊涂,连自己测的是什么都没搞清楚。

线程组和取样器,说白了就是压测脚本的骨架和肌肉。线程组决定「多少人同时干活」,取样器决定「干什么活」。这两个东西搞不明白,后面的参数化、断言、监听器全是白搭。

线程组:控制并发的基本单元

线程组在JMeter里叫Thread Group。你想想看,一个线程就是一个虚拟用户。100个线程就是100个虚拟用户同时发请求。

我个人习惯把线程组分成三类:

  • 普通线程组:最常用,适合大部分场景
  • setUp线程组:测试开始前执行,比如登录获取token
  • tearDown线程组:测试结束后执行,比如清理数据

配置线程组时,这几个参数要搞明白:

参数 说明 我的建议
Number of Threads 线程数,即并发用户数 从10开始逐步往上加
Ramp-Up Period 启动所有线程的时间 一般设成线程数/2,单位秒
Loop Count 每个线程循环次数 压测场景用Forever,配合持续时间
Same user on each iteration 每次迭代是否使用相同用户 参数化时一般勾选
注意:我曾经遇到过一个问题——Ramp-Up设得太短,导致服务器瞬间被冲垮,结果以为是代码问题,排查了半天才发现是压力陡增造成的。建议压测时Ramp-Up至少30秒以上,给服务器一个缓冲。

取样器:真正干活的组件

取样器就是JMeter里发送请求的组件。HTTP请求是最常用的,但还有JDBC请求、Java请求、SOAP/XML-RPC请求等等。

HTTP请求取样器的核心配置:

  • 协议:http或https,注意端口号
  • 服务器名称或IP:目标地址,别写错了
  • 端口号:默认80(http)或443(https)
  • 方法:GET、POST、PUT、DELETE等
  • 路径:接口的具体路径
  • 参数:GET参数或POST表单数据
  • Body Data:POST的JSON/XML数据
小技巧:调试时可以在HTTP请求下加一个「查看结果树」监听器,能看到请求和响应的完整内容。但正式压测时记得删掉,否则内存会爆。

HTTP请求默认值:少写重复代码

你想想看,如果一个系统有几十个接口,每个HTTP请求都要写一遍服务器IP、端口、协议、编码……是不是很烦?

HTTP请求默认值就是干这个用的。它像一个全局配置,所有HTTP请求取样器都会继承它的设置。

配置方法很简单:

  1. 在线程组下右键 → 添加 → 配置元件 → HTTP请求默认值
  2. 填入服务器IP、端口、协议、Content-Type等公共信息
  3. 所有HTTP请求取样器只需要写路径和参数即可

举个例子:

HTTP请求默认值配置:
  协议:https
  服务器:api.example.com
  端口:443
  内容编码:UTF-8

HTTP请求取样器只需要写:
  路径:/v1/user/login
  方法:POST
  Body:{"username":"test","password":"123456"}
核心思路:把不变的抽出来,把变化的留下来。这是脚本设计的基本原则。

我在项目中遇到过一个问题——测试环境切换时,要改几十个HTTP请求的IP地址。后来用了HTTP请求默认值,改一个地方就全变了。嗯,省了不少事。

参数化与CSV数据文件:让脚本动起来

压测时如果所有用户都用同一个账号、同一份数据,那测出来的结果基本没什么参考价值。为什么?因为服务器会缓存、会限流、会做重复数据判断。

参数化就是让每个虚拟用户用不同的数据。最常用的方式就是CSV数据文件。

CSV数据文件配置

配置步骤:

  1. 准备一个CSV文件,第一行是变量名,后面是数据
  2. 在线程组下添加「CSV数据文件设置」
  3. 配置文件名、变量名、分隔符等

CSV文件示例:

username,password,phone
user001,pass123,13800000001
user002,pass456,13800000002
user003,pass789,13800000003

CSV数据文件设置的关键参数:

参数 说明 推荐值
Filename CSV文件路径 使用相对路径,方便迁移
Variable Names 变量名,用逗号分隔 与CSV第一行对应
Delimiter 分隔符 一般用逗号,注意转义
Recycle on EOF 文件读完是否循环 压测场景建议勾选
Stop thread on EOF 文件读完是否停止线程 数据量够用时不勾选
Sharing mode 数据共享模式 All threads(所有线程共享)
避坑指南:我曾经因为CSV文件路径写错了,压测跑了半小时才发现所有用户用的都是第一行数据。建议在脚本里加一个「调试取样器」或「用户参数」,先验证参数化是否生效。

其他参数化方式

除了CSV,还有几种参数化方式:

  • 用户定义的变量:适合少量固定值,比如环境地址
  • 用户参数:每个线程独立的值,适合小规模参数化
  • 函数助手:比如__Random、__UUID、__time,适合生成随机数据
  • JDBC请求:从数据库读取数据,适合复杂场景

我个人习惯是:小规模用用户参数,大规模用CSV,需要动态生成用函数助手。没有绝对的好坏,看场景。

知识体系总览

下面这张图把本章的核心内容串起来了。你可以对照着看看,自己有没有遗漏的地方。

脚本编写篇核心知识体系 线程组 取样器 参数化 普通线程组 setUp / tearDown 线程数 / Ramp-Up HTTP请求 JDBC / Java请求 HTTP请求默认值 CSV数据文件 用户参数 / 变量 函数助手 核心原则 1. 线程组控制并发规模,取样器定义具体行为 2. 公共配置抽到默认值,减少重复代码 3. 参数化让数据动起来,压测才有意义
我的经验:刚开始学JMeter时,我总想把所有东西都塞到一个线程组里。后来发现,不同场景拆成不同线程组,用setUp做前置操作,用tearDown做清理,脚本清晰多了,排查问题也快。

嗯,线程组、取样器、HTTP请求默认值、参数化,这四个东西搞明白了,脚本编写的基础就算打牢了。剩下的就是多练、多踩坑、多总结。

想要更多资料,联系可可