Jmeter 动态参数压力测试时间段预定接口

🎯 本文档详细介绍了如何使用Apache JMeter进行压力测试,以评估预定接口在高并发场景下的性能表现。通过创建线程组模拟不同数量的用户并发请求,利用CSV文件动态配置时间段ID和用户token,确保了测试数据的真实性和有效性。文档中还展示了如何设置JMeter的各项参数、添加HTTP请求头、查看结果树和聚合报告等操作步骤。最终,通过一次针对4000用户并发的压测实例,分析了样本数、响应时间、异常率及吞吐量等关键指标,验证了系统的稳定性和可靠性。
🏠️ HelloDam/场快订(场馆预定 SaaS 平台)

文章目录

  • 压力测试
  • Jmeter介绍
  • 测试目标
  • 数据准备
  • Jmeter如何进行操作
    • Jmeter设置
    • 创建线程组
    • 创建 HTTP 请求
    • 添加请求头
    • 添加查看结果树、聚合报告
    • 动态参数
      • 给请求参数配置不同的时间段ID
        • 依赖
        • CSV生成代码
        • 绑定CSV文件
      • 配置不同的用户token
        • CSV 生成
        • 绑定 CSV 文件
    • 简单测试
  • 正式压测
    • 测试环境
    • 内存预热
    • 压力测试
    • Jmeter结构

压力测试

为了评估和测量接口在高负载情况下的性能表现。压力测试通常用于确定系统在预期的最大负载下的运行情况,识别系统可能存在的性能瓶颈,以及验证系统的稳定性和可靠性。压力测试对于确保应用程序能够支持特定数量的并发用户或操作至关重要。

Jmeter介绍

Apache JMeter 是一款开源的、基于Java的性能测试工具,主要用于测试静态和动态资源(如静态文件、Java Servlets、CGI脚本、数据库和其他基于Web的应用程序资源等)的性能。它最初设计用于Web应用测试但后来扩展到其他测试领域。JMeter可以用来模拟大量用户并发访问目标服务,以此来分析在不同负载条件下应用的性能表现。此外,它支持多种协议和技术,包括HTTP、HTTPS、FTP、SOAP、REST、LDAP、TCP、SMTP等,极大地增强了其灵活性和适用范围。JMeter的一大优点是它能够以图形界面或命令行模式运行,而且由于它是用Java编写的,因此可以在任何安装了Java虚拟机的平台上使用,具有很好的跨平台性。

  • 官网:https://jmeter.apache.org/
  • 下载地址:https://jmeter.apache.org/download_jmeter.cgi

测试目标

测试时间段预定接口在不同并发用户下的吞吐量。

数据准备

为了让测试结果更加有参考性,需要尽量模拟现实生活中的预定逻辑,即肯定是有多个用户同时进行预定,且预定的场馆、分区、时间段都可能不同。因此我们需要先模拟生成一些数据,其中包括场馆、分区、时间段模板、时间段。最终需要传给Jmeter的数据有:

  • 可接受预定的不同时间段 id
  • 不同用户登录之后的 token

Jmeter如何进行操作

Jmeter设置

修改为白色外观

在这里插入图片描述

设置为简体中文,方便操作,如果你英语好,当我没说,哈哈哈

在这里插入图片描述

创建线程组

创建线程组是一个基础且关键的步骤。线程组主要用来模拟用户对服务器或应用程序发起请求的行为。具体来说,它定义了虚拟用户的数目(即线程数)、这些用户将如何行动以及它们执行动作的时间安排(如启动时间、持续时间和关闭时间)。

在这里插入图片描述

初步设置如下参数,后续在进行压力测试的时候,可以从小到大调整线程数等参数

  • 一个线程代表一个用户,每个用户对不同时间段发起多次请求,可以先从50个用户开始,逐步增加到500或1000个用户,观察接口的性能变化
  • 循环次数:每个线程发请求的数量,相当于一个用户发起多少次预定
  • Ramp-Up时间:设置为5秒,表示这1000个线程,会在5秒内均匀启动起来,每个线程之间的启动间隔大约为 5/1000 秒

在这里插入图片描述

创建 HTTP 请求

预订接口如下:

@GetMapping("/v1/reserve")
public Result reserve(@RequestParam("timePeriodId") Long timePeriodId) {OrderDO orderDO = timePeriodService.reserve(timePeriodId);return Results.success(orderDO);
}

在这里插入图片描述

这里需要设置服务所在IP、端口,以及请求的接口路径。因为预定的时候,需要指明是哪个时间段,所以需要在参数中进行设置

在这里插入图片描述

添加请求头

由于用户在预定时间段的时候,需要先从用户登录之后的 token 信息中获知用户是谁,所以我们需要将 token 设置到请求头中

在这里插入图片描述

注意:除了设置 token 之外,还需要添加Content-typeapplication/json,后端接口才能正常解析 json 数据

在这里插入图片描述

添加查看结果树、聚合报告

  • 结果树:用来查看请求的请求参数、响应结果
  • 聚合报告:用来查看这些请求的统计信息

在这里插入图片描述

动态参数

因为我们需要模拟不同用户预定不同时间段的行为,这期间用户、时间段都有多个,因此,我们不能写死 HTTP 请求中的请求参数,而是需要使用动态参数,从 CSV 文件中读取数据,然后动态设置到不同的请求中

给请求参数配置不同的时间段ID

依赖

CSV导出直接写一个单元测试类即可,首先引入测试相关的依赖

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
CSV生成代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vrs.domain.entity.TimePeriodDO;
import com.vrs.service.TimePeriodService;
import com.vrs.utils.TxtUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;import java.io.File;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.List;/*** 可预定时间段id CSV 导出** @Author dam* @create 2025/1/12 15:06*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {VrsVenueApplication.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ReserveTestCSVGenerateTest {@Autowiredprivate TimePeriodService timePeriodService;/*** csv地址*/private final String csvPath = Paths.get("").toAbsolutePath().getParent().getParent() + File.separator + "tmp" + File.separator + "场馆预定时间段.csv";@Testpublic void generate() throws Exception {StringBuilder stringBuilder = new StringBuilder();QueryWrapper<TimePeriodDO> queryWrapper = new QueryWrapper<>();// 只查询在今天和今天之后的可预订时间段queryWrapper.ge("period_date", LocalDate.now());List<TimePeriodDO> timePeriodDOList = timePeriodService.list(queryWrapper);for (TimePeriodDO timePeriodDO : timePeriodDOList) {stringBuilder.append(timePeriodDO.getId() + "\n");}TxtUtil.write(new File(csvPath), stringBuilder.toString(), "utf-8");}
}

通过下面的注解为基于Spring Boot的应用程序提供全面的测试支持,包括依赖注入、应用上下文的配置以及Web环境的模拟等,这样我们才可以注入TimePeriodService来进行查询数据库等操作

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {VrsVenueApplication.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

导出的CSV文件如下图所示

在这里插入图片描述

绑定CSV文件

最后一步是给请求绑定 CSV 文件

在这里插入图片描述

设置CSV文件路径

在这里插入图片描述

最后在请求的参数中使用,通过表头列名来绑定数据,使用方式为${列名}

在这里插入图片描述

配置不同的用户token

CSV 生成
import com.vrs.domain.entity.UserDO;
import com.vrs.service.UserService;
import com.vrs.utils.TxtUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;import java.io.File;
import java.nio.file.Paths;
import java.util.List;/*** 模拟用户数据生成** @Author dam* @create 2025/1/12 15:06*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {VrsAdminApplication.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserTokenCSVGenerateTest {@Autowiredprivate UserService userService;/*** csv地址*/private final String csvPath = Paths.get("").toAbsolutePath().getParent().getParent() + File.separator + "tmp" + File.separator + "用户token.csv";@Testpublic void generate() throws Exception {StringBuilder stringBuilder = new StringBuilder();List<UserDO> userDOList = userService.list();for (UserDO userDO : userDOList) {// 登录并返回一个tokenstringBuilder.append(userService.handleLogin(userDO).getToken() + "\n");}TxtUtil.write(new File(csvPath), stringBuilder.toString(), "utf-8");}
}
绑定 CSV 文件

在这里插入图片描述

在这里插入图片描述

简单测试

完成上面的操作之后,启动压力测试即可,在查看结果树中,可以看到每个请求是否成功,响应结果是什么

在这里插入图片描述

接口错误的原因

在这里插入图片描述

在汇总报告中,可以查看压力测试的统计数据,例如接口调用时间的平均值、最小值、最大值,吞吐量……,这里异常那么高的原因是:用户已经购买过相应时间段或者时间段已经售罄

在这里插入图片描述

正式压测

测试环境

【测试机器】

  • 名称:MacBook Pro 2023
  • 尺寸:14英寸
  • CPU:m2 pro丐版芯片(6个性能核心、4个能效核心)
  • 内存:16GB

【服务启动方式】

为了模拟真实分布式环境下的性能表现,项目使用微服务方式启动

内存预热

为了在预定的时候可以快速查询,首先对需要使用到缓存进行预热,这里涉及的缓存有时间段信息、时间段库存、时间段位图

package com.vrs;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vrs.constant.RedisCacheConstant;
import com.vrs.domain.entity.PartitionDO;
import com.vrs.domain.entity.TimePeriodDO;
import com.vrs.service.PartitionService;
import com.vrs.service.TimePeriodService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;import java.time.LocalDate;
import java.util.List;/*** 时间段预定缓存预热** @Author dam* @create 2025/1/12 15:06*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {VrsVenueApplication.class})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TimePeriodCacheLoadTest {@Autowiredprivate TimePeriodService timePeriodService;@Autowiredprivate PartitionService partitionService;@Testpublic void generate() throws Exception {QueryWrapper<TimePeriodDO> queryWrapper = new QueryWrapper<>();// 只查询在今天和今天之后的可预订时间段queryWrapper.ge("period_date", LocalDate.now());List<TimePeriodDO> timePeriodDOList = timePeriodService.list(queryWrapper);for (TimePeriodDO timePeriodDO : timePeriodDOList) {timePeriodService.getTimePeriodDOById(timePeriodDO.getId());PartitionDO partitionDO = partitionService.getPartitionDOById(timePeriodDO.getPartitionId());// 首先检测空闲场号缓存有没有加载好,没有的话进行加载timePeriodService.checkBitMapCache(String.format(RedisCacheConstant.VENUE_TIME_PERIOD_FREE_INDEX_BIT_MAP_KEY, timePeriodDO.getId()), timePeriodDO.getId(), partitionDO.getNum());// 其次检测时间段库存有没有加载好,没有的话进行加载timePeriodService.getStockByTimePeriodId(timePeriodDO.getId());}}
}

预热之后的缓存如下:

在这里插入图片描述

压力测试

测试参数如下:

  • 线程数:4000
  • 循环次数:10
  • Ramp-Up时间

即模拟4000个用户进行场馆预定,每个用户分别发送20次预定请求,线程在20秒内启动完成

在这里插入图片描述

测试结果如下:

在这里插入图片描述

  1. 样本数量:总共有40,000个样本,这表示在测试期间进行了40,000次请求或操作。
  2. 响应时间
    1. 平均值:6036毫秒,表示所有请求的平均响应时间。
    2. 中位数:6442毫秒,表示50%的请求响应时间低于此值。
    3. 90%百分位:7155毫秒,表示90%的请求响应时间低于此值。
    4. 95%百分位:7264毫秒,表示95%的请求响应时间低于此值。
    5. 99%百分位:7482毫秒,表示99%的请求响应时间低于此值。
    6. 最小值:2毫秒,表示最快的请求响应时间。
    7. 最大值:26692毫秒,表示最慢的请求响应时间。
  3. 异常率:7.84%的请求出现了异常,当然这里的异常是:时间段售罄、时间段过期之类的。
  4. 吞吐量:508.3次请求/秒,表示系统在测试期间每秒处理的请求数量。
  5. 网络流量
    1. 接收速率:284.68 KB/sec,表示系统每秒接收的数据量。
    2. 发送速率:248.40 KB/sec,表示系统每秒发送的数据量。

Jmeter结构

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/67979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity常用特性(Attribute)用法

一.UnityEngine命名空间 1.[Header(string)] inspector面板上给显示的字段上加一个描述 通常情况下&#xff0c;用于在 Inspector 窗口中创建字段的逻辑分组 public class AttributeTest : MonoBehaviour {[Header("public_field_num")]public int num; }2.[Tool…

vue项目的创建

运行第一个vue-cli应用程序 创建一个基于webpack模板的vue应用程序 vue init webpack 项目名根据自己需求选择 创建好之后如下 运行 cd vue01npm run dev运行之后如下 复制访问地址 &#xff1a; http://localhost:8080 停止服务 两次ctrlC 或者 一次ctrlc然后y idea中使用…

【CS61A 2024秋】Python入门课,全过程记录P3(Week5 Sequences开始,更新于2025/1/23)

文章目录 关于基本介绍&#x1f44b;新的问题Week5Mon Sequences阅读材料 关于 个人博客&#xff0c;里面偶尔更新&#xff0c;最近比较忙。发一些总结的帖子和思考。 江湖有缘相见&#x1f91d;。如果读者想和我交个朋友可以加我好友&#xff08;见主页or个人博客&#xff0…

android手机应用连接热点后无法进行tcp连接

你在WifiNetworkSpecifer连接回调onavaliable里&#xff0c;再次调用bindProcessToNetwork试试&#xff0c;我这边模拟了一下&#xff0c;是可以建立tcp连接的 你的那个应用我一直没编译成功&#xff0c;你试试吧&#xff0c;应该这样是可以的 另一个同事找到了类似的方法&…

【华为路由的arp配置】

华为路由的arp配置 ARP&#xff1a;IP地址与MAC地址的映射。 R1: g0/0/0:10.1.1.254/24 g0/0/1:10.1.2.254/24 PC1: 10.1.1.1/16 PC2: 10.1.1.2/16 PC3: 10.1.2.3/16 动态ARP 查看PC1的arp表&#xff0c;可以看到&#xff0c;列表为空。 查看R1的arp表 在PC3上ping命令测…

SPDK vhost介绍

目录 1. vhost技术的背景与动机Virtio 介绍virtio-blk数据路径为例 2. vhost技术的核心原理2.1 vhost-kernel2.2 vhost-user举例 2.3 SPDK vhostvhost的优势IO请求处理数据传输控制链路调整 3. SPDK vhost的实现与配置3.1 环境准备3.2 启动SPDK vhost服务3.3 创建虚拟块设备3.4…

电容的一些常用数值

如果是滤高频信号的小电容一般采用100nF 如果是滤低频信号的大电容一般采用10uF(10000nF) 比如这个LDO降压 两个一起用滤波效果会更好 如果想要供电引脚悬空&#xff0c;按理不能悬空&#xff0c;所以应该接大电阻接地&#xff0c;一般采用5.1KΩ 比如这个6Pin USB-TypeC的…

一个基于Python+Appium的手机自动化项目~~

本项目通过PythonAppium实现了抖音手机店铺的自动化询价&#xff0c;可以直接输出excel&#xff0c;并带有详细的LOG输出。 1.excel输出效果: 2. LOG效果: 具体文件内容见GitCode&#xff1a; 项目首页 - douyingoods:一个基于Pythonappium的手机自动化项目&#xff0c;实现了…

(回溯分割)leetcode93 复原IP地址

#include<iostream> #include<vector> #include<string> #include<algorithm> using namespace std; //卡尔的图不是按照程序执行过程而是直接画程序会执行的过程 // 实际执行是&#xff1a;n个字符&#xff0c;递推n1后&#xff08;叶子节点&#xff…

分子动力学模拟里的术语:leap-frog蛙跳算法和‌Velocity-Verlet算法

分子动力学模拟&#xff08;Molecular Dynamics Simulation&#xff0c;简称MD&#xff09;是一种基于经典力学原理的计算物理方法&#xff0c;用于模拟原子和分子在给定时间内的运动和相互作用‌。以下是关于分子动力学模拟的一些核心术语和概念&#xff1a; ‌定义系统‌&am…

智能工厂数字化化集成落地项目(交付版 67页)PPT 解读

基于工业4.0和工业智能化转型的甲方智能工厂数字化集成落地项目。报告分析了制造业的发展趋势&#xff0c;重点介绍了甲方为应对挑战而实施的商业模式创新和产业升级策略。通过引入乙方的智能工厂规划&#xff0c;构建了一个集成的数字化工厂架构&#xff0c;以提高生产效率和响…

Linux进度条实现

Linux进度条实现 1.\r\n2.缓冲区3.缓冲区分类4.进度条实现 &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列专栏&#xff1a;【Linux的学习】 &#x1f4dd;&#x1f4dd;本篇内容&#xff1a;\…

基于java线程池和EasyExcel实现数据异步导入

基于java线程池和EasyExcel实现数据异步导入 2.代码实现 2.1 controller层 PostMapping("import")public void importExcel(MultipartFile file) throws IOException {importService.importExcelAsync(file);}2.2 service层 Resource private SalariesListener sa…

校验收货地址是否超出配送范围实战3(day09)

优化用户下单功能&#xff0c;加入校验逻辑&#xff0c;如果用户的收货地址距离商家门店超出配送范围&#xff08;配送范围为5公里内&#xff09;&#xff0c;则下单失败。 提示&#xff1a; ​ 1. 基于百度地图开放平台实现&#xff08;https://lbsyun.baidu.com/&#xff09…

Linux系统下速通stm32的clion开发环境配置

陆陆续续搞这个已经很久了。 因为自己新电脑是linux系统无法使用keil&#xff0c;一开始想使用vscode里的eide但感觉不太好用&#xff1b;后面想直接使用cudeide但又不想妥协&#xff0c;想趁着这个机会把linux上的其他单片机开发配置也搞明白&#xff1b;而且非常想搞懂cmake…

leetcode_3092. 最高频率的 ID

https://leetcode.cn/problems/most-frequent-ids/description/ 看到这个数据范围 最极端情况 如果nums全为一个数 并且数量取到最大 那么范围是10的10次方 需要longlong储存 这题主要运用了哈希表配合multiset实现 哈希表主要用作存储某个数的出现次数 mst则用于记录出现次…

【深度学习】 自动微分

自动微分 正如上节所说&#xff0c;求导是几乎所有深度学习优化算法的关键步骤。 虽然求导的计算很简单&#xff0c;只需要一些基本的微积分。 但对于复杂的模型&#xff0c;手工进行更新是一件很痛苦的事情&#xff08;而且经常容易出错&#xff09;。 深度学习框架通过自动…

如何把jupyter的一个.ipynb文件的多个单元格cell合并为1个cell

1 jupyter的一个.ipynb文件的多个单元格cell合并为1个cell 步骤 1&#xff1a;打开 your_notebook.ipynb 文件 启动 Jupyter Notebook。 导航到你的工作目录&#xff08;例如 F:\main&#xff09;。 打开 your_notebook.ipynb 文件。 步骤 2&#xff1a;选择所有单元格 点击…

集成Sleuth实现链路追踪

文章目录 1.新增sunrays-common-cloud模块1.在sunrays-framework下创建2.pom.xml3.查看是否被sunrays-framework管理 2.创建common-cloud-sleuth-starter1.目录结构2.pom.xml3.sunrays-dependencies指定cloud版本4.SleuthAutoConfiguration.java5.spring.factories 3.创建commo…

WPF基础 | 初探 WPF:理解其核心架构与开发环境搭建

WPF基础 | 初探 WPF&#xff1a;理解其核心架构与开发环境搭建 一、前言二、WPF 核心架构2.1 核心组件2.2 布局系统2.3 数据绑定机制2.4 事件处理机制 三、WPF 开发环境搭建3.1 安装 Visual Studio3.2 创建第一个 WPF 应用程序 结束语优质源码分享 WPF基础 | 初探 WPF&#xff…