性能测试
一、基本概念
1. 性能
吞吐量TPS:服务器每秒处理的业务请求个数
响应时间:从客户端发送请求,到客户端接收到响应的总时间
错误率:错误的请求样本数在总请求样本数中的占比(即:错误请求样本数/总请求样本数)性能:就是软件质量模型中的“效率"特性
- 效率特性:
- 时间特性:表示系统处理用户请求的响应时间
- 资源特性:表示系统运行过程中,系统资源的消耗情况,如:CPU、内存、磁盘等
2. 性能测试
- 性能测试:使用工具,模拟,对软件的进行测试和评估
- 自动化工具:JMeter、Locust
- 不同场景:如用户长时间使用、超大量用户同时在线、大量用户同时使用
- 软件各项性能指标:时间、资源
3. 性能测试的作用
- 系统上线后,评估系统能力
- 系统上线后,寻找性能瓶颈,优化性能(找bug,一般是易用性差,如抢票系统在大量用户同时购票抢票时会出现系统繁忙导致部分用户买不到票)
- 评估软件能否满足未来的需要
4. 性能测试与功能测试的区别与联系
- 功能测试:验证软件系统操作功能是否符合产品,主要焦点在功能()
- 性能测试:验证软件系统是否满足,主要焦点是业务场景的满足()
- 性能测试只测正向功能,不测逆向功能
一般项目中,先通过后,再进行
5. 性能测试业务场景介绍
- 单业务场景:此场景单独测试每一个业务/接口,各业务/接口
单独进行压测,判断性能是否满足需求- 压测:压力测试
- 例如:(1)登录(2)搜索(3)下订单,三个业务/接口
单独进行性能压测
- 混合业务场景:测试系统中的多个业务/接口,按照业务比例,对多个接口
同时进行压测,判断是否有性能问题- 一般情况下,仅当单业务场景测试完毕后,再进行混合业务场景测试
- 峰值场景:此场景要验证系统在某段时间内或请求量波动较大的情况下,系统能否正常稳定的提供服务
- 例如:电商双11场景;限时秒杀场景
- 稳定性测试场景:主要测试系统在一定压力下,长时间运行 能否保持稳定运行
- 例如:电商系统,同时进行 登录、搜索、下订单、发货、退货、退款等业务操作,运行7*24小时,看看系统能否稳定运行
- 一般仅当前面几个测试场景都测试完毕后,才考虑进行稳定性测试
- 异常场景:主要测试系统在出现故障/异常后,验证业务是否受到影响,以及受影响的时间(多久能恢复)
- 例如:
- 社媒类软件出现热点话题,用户同时访问量远大于压测最大值,出现预期外的错误;
- 服务器集群中有部分服务器出现down机(无法访问),导致剩余的正常服务器承担所有的业务量,可能会承受不住
- 例如:
6. JMeter 与其他工具的区别
| 工具 | 脚本形式 | GUI 角色 |
|---|---|---|
| JMeter | XML 脚本(.jmx) | 可视化编辑器(拖拽组件) + 执行器 |
| Postman | JSON 脚本(Collection) | 接口调试 + 脚本管理 |
| Python + requests | Python 代码 | 纯代码,无专属 GUI(需借助 IDE) |
| LoadRunner | C/Vuser 脚本 | 类似 IDE 的专业脚本编辑器 |
JMeter 的独特之处在于:即使完全不懂 XML,也能通过 GUI 完成复杂的压测脚本编写。
7. JMeter介绍
结构如下:
测试计划
---线程组A
---线程组B- 测试计划中的线程组之间:默认是并行的。
- 若勾选测试计划界面下方的 “独立运行每个线程组”。JMeter 会按顺序执行测试计划中的线程组:先启动线程组 A,等 A 中所有线程(无论设置了多少循环)都完全停止后,再启动线程组 B。
- 单个线程组内的请求之间:默认是串行的。JMeter 会按顺序从上到下执行同一个线程组里的请求。
- 配置元件是在测试启动时全局加载的,它们的作用域由其所在的“树形结构”位置决定,与线程组之间的执行顺序(串行/并行)没有直接关系。
二、具体场景分析
以下的场景分析使用的例子均为BMS系统(包含登录、进入首页、获取用户信息、退出四个业务功能)TPS(吞吐量):每秒处理的请求数量
1. 单业务场景
单业务可能是单个接口,也可能是多个接口Q:为什么要进行单业务测试? A:要验证系统能支持的单业务/接口的最大负载量,能否满足系统业务需求,单业务测试达标后才能进行混合业务测试
- 以登录为例,假设某BMS系统目标登录TPS为30,进行如下步骤的性能测试:
- 模拟单个用户,发送请求,收集基准性能数据(TPS和响应时间) ----
- 逐步增加用户量,发送请求,收集性能测试数据 ----
- 将系统能支持的最大TPS,与需求进行对比,达标则测试通过
例如: case1:模拟1个用户,发送登录请求,记录TPS和响应时间 case2:模拟10个用户,发送登录请求,记录TPS和响应时间 case3:模拟20个用户,发送登录请求,记录TPS和响应时间 case4:模拟30个用户,发送登录请求,记录TPS和响应时间 case5:模拟40个用户,发送登录请求,记录TPS和响应时间 ...... 假设结果:
关键点
- 设置性能测试场景(即:按照用例要求模拟大量用户发送请求)
- 通过JMeter的 线程组 配置(线程组就是用户数,一个线程代表一个虚拟用户)
- 收集性能测试数据(即:记录TPS和响应时间)
- 通过 聚合报告 收集
- 分析性能测试结果
- 找出系统的最大TPS,与需求进行对比,达标则通过
a. 线程组
特点:
模拟多人操作
线程组可以添加多个,多个线程组可以并行或串行
取样器(请求)和逻辑控制器必须依赖线程组才能使用
线程组下可以添加其他元件下的组件
线程组分类:
线程组:普通常用的线程组,可以看作一个虚拟用户组,线程组中的每一个线程都可以看做是一个虚拟用户
setUp线程组:一种特殊类型的线程组,可以用于执行预测试操作(在所有线程组前进行操作)
tearDown线程组:一种特殊类型的线程组,可以用于执行测试后操作(在所有线程组后进行操作)- 作用:控制JMeter用于执行测试的一组用户,可以模拟多人操作
- 常用参数:

- 循环次数:永远 --> 线程会一直运行,模拟的是用户长时间使用的场景
- 调度器:可以设置持续时间、启动延迟等参数,若勾选了调度器,并规定持续时间,则线程组会一直运行直到调度器设定的持续时间结束
- 详细参数:

- 启动延迟:仅适用于处理多个业务之间有先后关系的场景
只有当循环次数选择“永远”时,勾选调度器后设置的调度器配置才会起作用
b. 聚合报告(收集其父节点下的所有同级和后代取样器的数据)
- 作用:收集性能测试结束后系统的各项性能指标。如:响应时间、吞吐量(TPS)、错误率等。
- 位置:测试计划 -> 右键 -> 监听器 -> 聚合报告
- 参数:

- 响应时间:单位
ms
- 响应时间:单位
c. 分析性能测试结果
将聚合报告统计结果记录到表格中
3)如何进行性能测试
- 打开JMeter,新建测试计划 -> 新建线程组 -> 在线程组内新建HTTP请求
查看结果树用于查看测试脚本是否成功运行 - 在项目jar包所在目录运行命令
java -jar bms2-1.0-SNAPSHOT.jar,开始在本地运行项目 - 设定线程组

- Same User on each iteration选项:
- 勾选:适合模拟有状态的业务场景(用户持续操作多轮)
- 不勾选:适合模拟无状态的压测(每次循环都是全新用户)
- Same User on each iteration选项:
- 根据BMS系统接口文档设定HTTP请求(更推荐使用Postman来测试接口是否能正常使用,使用Postman测试接口就不需要结果树了,直接跳转至第六步)(本地部署,则IP替换为127.0.0.1)

- 编写完成后记得先保存再运行,运行后查看结果树,运行成功则说明没有问题,可以继续进行压测,必须先调通脚本再测试

- 为线程组添加聚合报告,随后启动JMeter脚本,聚合报告会自动获取该线程组的数据

- 根据聚合报告数据,使用Excel表格记录性能测试数据
- 更改线程组的线程数,启动JMeter脚本,重复7~8步
2. 混合业务场景
负载测试:验证系统在预期负载下是否满足性能要求
压力测试(压测):找到系统的极限上限和崩溃点- 混合业务场景测试分析:所有业务/接口 按比例 发送请求(因为用户常用的业务就几种,其余业务用的少,比例就少)
- 测试步骤:
- 进行基准测试
- 再进行负载测试
- 将系统能支持的最大TPS,与需求进行对比,所有业务 达标则测试通过
关键点
- 设置性能测试场景(即:模拟多用户 + 按照比例发送请求)
- 通过 吞吐量控制器 配置
- 收集性能测试数据(即:记录TPS和响应时间)
- 通过聚合报告实现
- 分析性能测试结果
- 找出系统的总计最大TPS,与需求总计TPS进行对比,达标则通过
- 因为业务请求数是按比例分配的,其TPS也是按比例分配的,总TPS达标,对应每个业务的TPS也应该是达标的
- 找出系统的总计最大TPS,与需求总计TPS进行对比,达标则通过
吞吐量控制器(作为指定HTTP请求的父节点)
作用:控制其下的子节点的执行次数与负载比例分配 参数:
与单业务场景不同,混合业务场景需要先在线程组下添加吞吐量控制器,再在吞吐量控制器下添加HTTP请求,以确保HTTP请求按照吞吐量控制器的配置执行
例如:BMS系统有登录、访问首页、获取用户信息、退出 这四项业务功能,它们的TPS要求分别是30、20、10、20,则配置吞吐量控制器,为这四项业务分配的吞吐量比例分别为37.5、25、12.5、25,最后根据聚合报告得到的数据也可验证是否按业务比例分配请求数:
可以通过验算样本数占比 或 吞吐量(TPS)占比 来判断是否成功按照业务比例分配请求数
3. 峰值场景测试性能分析(并发测试)
我们指的峰值场景一般指的是决対并发场景
Q:什么是峰值场景测试? A:在内,发送,验证服务器对并发的处理能力
示例:
- 项目背景:BMS系统每日9点签到,会有50个用户陆续上线,其中40个用户在9点整同时登陆系统进行签到
- 性能需求分析:
- 有50个用户陆续上线,表示:有50个用户发送登录请求 ----
- 有40个用户在9点整同时登录系统,表示:有40个用户同一时刻发送登录请求 ----
- 目标:
- 首先关注错误率,最好为0
- 其次关注吞吐量/响应时间,响应时间可能会上升,但峰值结束后能慢慢恢复即可
操作步骤:
- 添加线程组,设置线程数50
- 添加HTTP请求 -- 登录
- 添加同步定时器,并发数 设置40,超时时间为5000 ms
- 添加监听器 -- 聚合报告
关键点
- 有50用户陆续上线(相对并发)
- 线程组,设置线程数
- 有40用户在9点整同时登录系统(绝对并发)
- 同步定时器
同步定时器(作为指定HTTP请求的子节点)
- 作用:阻塞线程(累积一定的请求),当在规定的时间内到达一定的线程数量,这些线程会在同一个时间点一起释放,瞬间产生很大的压力
- 想象一下,同步定时器其实是一个"集合点",它的作用是让线程都在某一时刻停在"集合点"等待其他线程到达(阻塞),一定时间内"集合点"中的线程数达到一定程度,这些就会从"集合点"一起出发(释放)
- 位置:测试计划 --> 线程组 --> HTTP请求 --> (右键添加)定时器 --> Synchronizing Timer
- 参数:

- Number of Simulated Users to Group by: 模拟用户的数量,即指定。
- 若设置为0,等于设置为线程组中的线程数量
- Timeout in milliseconds: 超时时间,即 指定的线程数;
- 如果设置为0,该定时器将会等待线程数达到了设置的线程数才释放,若没有达到设置的线程数会一直死等。
- 如果大于0,那么如果超过Timeout in milliseconds中设置的最大等待时间后还没达到设置的线程数,Timer将不再等待,释放已到达的线程。默认为0
- Number of Simulated Users to Group by: 模拟用户的数量,即指定。
4. 稳定性测试场景性能分析
混合业务场景负载测试 和 峰值场景并发测试,都是验证 短时间内的系统处理能力 能否支持高负载
不同于以上两者,稳定性场景测试主要是发现 长时间运行 时(系统的使用和释放),系统能否稳定提供服务Q:什么是稳定性场景测试? A:在服务器的情况下进行,并最终保证服务器能满足线上业务需求
什么是用户正常的业务负载?
- 系统日常运行时,用户所进行的主要业务操作
- 解释:系统日常运行时,一定是多种业务共存,因此需要使用 混合业务场景 下的压力
- 系统日常运行时,每种业务操作的并发/负载量
- 解释:系统日常运行时,并不会永远保持高峰期的压力/负载量,因此压力可以比 高峰期混合业务场景 的压力低一些(例如:CPU使用率在70%时对应的并发数)
- 系统日常运行时,用户所进行的主要业务操作
测试时长一般是 1天 ~ 1周
示例:
- 项目背景:BMS系统日常业务(登录/进入首页/获取用户信息/退出),保证系统在日常情况下连续不间断运行
- 性能分析:
- 模拟用户正常业务负载量:
- 系统日常使用时,一般为混合业务场景(登录/进入首页/获取用户信息/退出)
- 稳定性运行TPS比之前混合场景测试时的最大TPS低一些(具体参照混合业务场景测试时记录的数据)
- 不间断运行一段时间(一般是 1天 ~ 1周)
- 观察性能指标
- 模拟用户正常业务负载量:
- 关注的指标:
- 首先关注错误率,最好为0
- 其次关注吞吐量/响应时间,响应时间(不会明显上升)和吞吐量(不会明显下降)长期处于稳定的范围内
- 操作步骤:
- 添加线程组,设置线程数和运行时间(24 * 3600)
- 线程数:参考混合业务场景测试数据,比最高TPS低一些
- 运行时间:24 * 3600 (因为在JMeter中,运行时间是以秒为单位计数的)
- 添加吞吐量控制器和HTTP请求,设置吞吐量比例
- 添加监听器 - 聚合报告
- 使用命令行运行JMeter脚本,生成HTML测试报告(GUI图形界面不能生成HTML测试报告)(需要在JMeter的bin目录下使用cmd命令行)
- HTML测试报告的作用:可以从测试计划中获取图表和统计数据信息
- cmd命令:jmeter -n -t [jmx file] -l [result file] -e -o [html report folder]
- eg:jmeter -n -t hello.jmx -l result.jtl -e -o ./report
- 参数描述:
-n: 非GUI模式执行Jmeter(不使用图形界面操作,即使用命令行方式运行)-t [jmx file]: 测试计划保存的路径及.jmx文件名,路径可以是相对路径也可以是绝对路径-l [result file]: 保存生成测试结果的文件,jtl文件格式(这是一个中间文件,报告是由该文件生成的,命名不太重要)-e: 测试结束后,生成测试报告-o [html report folder]: 存放生成测试报告的路径,路径可以是相对路径也可以是绝对路径
- 参数描述:
- 添加线程组,设置线程数和运行时间(24 * 3600)
关键点
- 设置性能测试场景(即:混合业务场景 + 长时间运行)
- 通过 吞吐量控制器 + 线程组 配置
- 收集性能测试数据(即:记录错误率、TPS和响应时间)
- 通过 聚合报告 收集(平均值)
- 通过 收集(过程数据,查看是否处于稳定的范围内)
- 分析性能测试结果
- 错误率为0
- 吞吐量/响应时间处于稳定的范围内
三、性能测试实战
1. 性能测试的步骤
各典型性能场景都会按照以下步骤分析执行- 项目性能现状评估
- 提取性能测试业务
- 编写性能测试脚本
- 搭建性能测试环境
- 执行性能测试,收集性能指标
- 项目需求指标分析
- 计算要达成的性能指标
- 项目性能测试执行
- 编写性能测试脚本
- 设置性能场景
- 执行性能测试,并分析结果
- 性能瓶颈分析调优(测试人员了解即可)
- 性能问题分析及解决
- 性能问题回归验证
- 性能测试总结报告
2. 提取性能测试业务
1)性能测试与功能测试的区别
- 功能测试:覆盖所有功能(正向、逆向) ---- 侧重:全面
- 性能测试:覆盖主流的业务场景(正向) ---- 侧重:精准
- 性能测试的用例数大概为功能测试的1%(数量少)
2)如何精准提取性能测试的业务
从以下两方面考虑:
- 业务(用户角度思考)
- 最简单的判断方法:从冒烟测试的业务中挑选,非冒烟测试业务不考虑
- 用户频繁使用的业务
- 非常关键的业务
- 技术(开发角度思考,公司里可以直接问开发哪些业务资源占用率高,就去测那些业务)
- 资源占用高的业务功能
3)JMeter常用测试元件
- 取样器-HTTP请求 --> 发送HTTP请求
- 配置元件-HTTP请求默认值 --> 设置HTTP请求中的默认(固定)部分
- 配置元件-用户定义的变量 --> 定义全局变量
- 后置处理器-JSON提取器 --> 提取JSON响应结果中的数据
- 断言-响应断言 --> 对任何响应结果中的数据进行检查
- 断言-JSON断言 --> 对JSON响应结果中的数据进行检查
- 监听器-察看结果树 --> 查看脚本执行后的HTTP请求和响应内容
- 监听器-聚合报告 --> 查看性能测试的指标数据