【黑马点评】使用RabbitMQ实现消息队列——3.使用Jmeter压力测试,导入批量token,测试异步秒杀下单
3 批量获取用户token,使用jmeter压力测试
- 3 批量获取用户token,使用jmeter压力测试
- 3.1 需求
- 3.2 实现
- 3.2.1 环境配置
- 3.2.2 修改登录接口UserController和实现类
- 3.2.3 测试类
- 3.3 使用jmeter进行测试
- 3.4 测试结果
- 3.5 将用户登录逻辑修改回去
3 批量获取用户token,使用jmeter压力测试
3.1 需求
优惠券秒杀的接口,需要模拟1000个不同登录用户下的秒杀场景,测试这个接口的性能。
分析
1.如何模拟这1000个用户?
我们可以使用for循环在数据库中批量添加这1000个用户,然后需要对这1000个用户进行登录以获取这1000个用户的token,以便在jmeter发起的请求头中携带这1000个token模拟1000个用户。
2.如何批量获取token?
编写脚本发起1000个登录请求,并将响应的token写入txt文件中。
3.2 实现
3.2.1 环境配置
1.修改pom.xml文件,导入apache包
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.6</version></dependency>
3.2.2 修改登录接口UserController和实现类
1.登录接口:修改UserController.java中的login方法为以下内容
本项目使用的是手机号和验证码登录方式,这两个参数携带在请求体(requestbody)中,而不是请求参数中(url路径中),如果根据手机号登录,需要将验证验证码的代码注释掉(即注释掉验证逻辑),以便直接根据手机号登录而无需验证。
/*** 登录功能* @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码*/
@PostMapping("/login")
public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){String phone = loginForm.getPhone();String code = loginForm.getCode();if(phone == null){return Result.fail("手机号为空!");}// if(code == null){
// return Result.fail("验证码为空!");
// }return userService.login(loginForm, session);}
修改实现类中的检验方法
主要注释掉校验验证码这部分的逻辑
// @TODO 先不校验验证码
/* if(cacheCode == null || !cacheCode.equals(code)){//3.不一致,报错return Result.fail("验证码错误");}*///注释掉以上部分
impl类中方法如下
@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {// 1.校验手机号String phone = loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合,返回错误信息return Result.fail("手机号格式错误!");}
// // 3.校验验证码
// Object cacheCode = session.getAttribute("code");// 3.从redis获取验证码并校验String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);String code = loginForm.getCode();// @TODO 先不校验验证码
/* if(cacheCode == null || !cacheCode.equals(code)){//3.不一致,报错return Result.fail("验证码错误");}*///注释掉以上部分//一致,根据手机号查询用户User user = query().eq("phone", phone).one();//5.判断用户是否存在if(user == null){//不存在,则创建user = createUserWithPhone(phone);}// 7.保存用户信息到 redis中// 7.1.随机生成token,作为登录令牌String token = UUID.randomUUID().toString(true);// 7.2.将User对象转为HashMap存储UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(), //beanToMap方法执行了对象到Map的转换CopyOptions.create().setIgnoreNullValue(true) //BeanUtil在转换过程中忽略所有null值的属性.setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString())); //对于每个字段值,它简单地调用toString()方法,将字段值转换为字符串。// 7.3.存储String tokenKey = LOGIN_USER_KEY + token;stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);// 7.4.设置token有效期stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.返回tokenreturn Result.ok(token);}
3.2.3 测试类
2.登录流程:
用户登录成功后,服务端会将token作为data数据返回给客户端,并将token存储到Redis中。之后客户端将token添加到请求头Authorization中,每次发起请求都需要携带该请求头,后端拦截器会根据请求头进行用户身份验证。
3.响应格式:
用户登录成功服务端响应格式
{“success”:true,“data”:“301130fd-7e25-4c93-8a79-9eb7d54c6fed”}//响应体
批量获取token脚本(Java)
思路:使用userService从数据库中获取用户集合(这里使用的是Mybatis-plus),遍历集合中的每个用户,将用户的手机号添加到请求体中,使用Java的Http客户端发起请求。之后从json响应体中获取token并写入txt文件中。
编写测试类(即脚本):

测试类内容如下:
package com.hmdp;import com.hmdp.entity.User;
import com.hmdp.service.IUserService;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.BufferedWriter;
import java.io.FileWriter;import java.util.List;
@SpringBootTest
public class UserLoginBatch {@Autowiredprivate IUserService userService;@Testpublic void function(){String loginUrl = "http://localhost:8080/api/user/login"; // 替换为实际的登录URLString tokenFilePath = "tokens.txt"; // 存储Token的文件路径try {HttpClient httpClient = HttpClients.createDefault();BufferedWriter writer = new BufferedWriter(new FileWriter(tokenFilePath));// 从数据库中获取用户手机号List<User> users = userService.list();for(User user : users) {String phoneNumber = user.getPhone();// 构建登录请求HttpPost httpPost = new HttpPost(loginUrl);//(1.如果作为请求参数传递)//List<NameValuePair> params = new ArrayList<>();//params.add(new BasicNameValuePair("phone", phoneNumber));// 如果登录需要提供密码,也可以添加密码参数// params.add(new BasicNameValuePair("password", "user_password"));//httpPost.setEntity(new UrlEncodedFormEntity(params));// (2.如果作为请求体传递)构建请求体JSON对象JSONObject jsonRequest = new JSONObject();jsonRequest.put("phone", phoneNumber);StringEntity requestEntity = new StringEntity(jsonRequest.toString(),ContentType.APPLICATION_JSON);httpPost.setEntity(requestEntity);// 发送登录请求HttpResponse response = httpClient.execute(httpPost);// 处理登录响应,获取tokenif (response.getStatusLine().getStatusCode() == 200) {HttpEntity entity = response.getEntity();String responseString = EntityUtils.toString(entity);System.out.println(responseString);// 解析响应,获取token,这里假设响应是JSON格式的// 根据实际情况使用合适的JSON库进行解析String token = parseTokenFromJson(responseString);System.out.println("手机号 " + phoneNumber + " 登录成功,Token: " + token);// 将token写入txt文件writer.write(token);writer.newLine();} else {System.out.println("手机号 " + phoneNumber + " 登录失败");}}writer.close();} catch (Exception e) {e.printStackTrace();}}// 解析JSON响应获取token的方法,这里只是示例,具体实现需要根据实际响应格式进行解析private static String parseTokenFromJson(String json) {try {// 将JSON字符串转换为JSONObjectJSONObject jsonObject = new JSONObject(json);// 从JSONObject中获取名为"token"的字段的值String token = jsonObject.getString("data");return token;} catch (Exception e) {e.printStackTrace();return null; // 解析失败,返回null或者抛出异常,具体根据实际需求处理}}
}
先运行HmDianPingApplication,之后运行测试类可得到存储了1000个用户token的txt文件


3.3 使用jmeter进行测试
1.设置线程数为1000

2.导入tokens文件

3.设置HTTP信息头管理器

4.设置HTTP请求
注意,Path为/api/voucher-order/seckill/13
13记得修改为自己的秒杀商品id

5.运行并得到结果
运行前,13的商品库存为100


3.4 测试结果

Redis和数据库中库存减为0


订单数量为100
3.5 将用户登录逻辑修改回去
取消验证码检测的注释。
相关文章:
【黑马点评】使用RabbitMQ实现消息队列——3.使用Jmeter压力测试,导入批量token,测试异步秒杀下单
3 批量获取用户token,使用jmeter压力测试 3 批量获取用户token,使用jmeter压力测试3.1 需求3.2 实现3.2.1 环境配置3.2.2 修改登录接口UserController和实现类3.2.3 测试类 3.3 使用jmeter进行测试3.4 测试结果3.5 将用户登录逻辑修改回去 3 批量获取用户…...
第 21 章 一条记录的多幅面孔——事务的隔离级别与 MVCC
21.1 事前准备 CREATE TABLE hero ( number INT, NAME VARCHAR ( 100 ), country VARCHAR ( 100 ), PRIMARY KEY ( number ) ) ENGINE INNODB CHARSET utf8;INSERT INTO hero VALUES ( 1, 刘备, 蜀 );21.2 事务隔离级别 在保证事务隔离性的前提下,使用不同的隔…...
javaScript操作dom的事件(3个案例+代码+效果图)
目录 1.焦点事件 案例:登录表单的验证 1.代码 2.效果 3.解释 2.鼠标事件 案例:单击鼠标使小球跳跃 1.代码 2.效果 3.解释 3.键盘事件 案例:使用左右键控制小球左右移动 1.代码 2.效果 编辑 3.解释 1.焦点事件 focus 当获得焦点时出发(不会冒泡)blur 当失去焦点时出发(不会…...
国庆期间的问题,如何在老家访问杭州办公室的网络呢
背景:国庆期间的问题,如何在老家访问杭州办公室的网络呢 实现方案:异地组网 实现语言:Java 环境:三个网络,一台拥有公网IP的服务器、一台杭州本地机房内服务器、你老家所在网络中的一台电脑(…...
动态规划算法——三步问题
1.题目解析 2.算法原理 本题可以近似看做泰波那契数列,即小孩到第一个台阶需要一步,到第二个台阶则是到第一个台阶的步数加上第一阶到第二阶的步数,同理第三阶就是第二阶的步数加上第二阶到第三阶的步数,由于小孩只能走三步&#…...
【鸿蒙学习】深入解析鸿蒙应用与元服务:含义、区别、应用场景及创建方法
文章目录 鸿蒙应用(HarmonyOS App)含义用于干什么优缺点 元服务(Atomic Service)含义用于干什么优缺点 鸿蒙应用与元服务的区别创建方法鸿蒙应用的创建元服务的创建 总结 随着科技的不断进步,操作系统也在不断迭代更新…...
React学习01 jsx、组件与组件的三大属性
文章目录 jsx的介绍与语法1.真实DOM和虚拟DOM2.jsx语法 模块与模块化,组件与组件化模块与模块化组件与组件化 React组件React事件绑定函数式组件类式组件组件属性state组件属性props组件属性ref 尚硅谷react教程官方文档学习记录笔记01 jsx的介绍与语法 1.真实DOM和…...
项目——超级马里奥——Day(3)
一、游戏开发思路: 1.Frame--->BackGround--->Obstacle---->BufferedImage,人物等 2.BackGround的构造函数: 只要记住窗口里边的每一个场景,只要游戏一开始就已经出现在屏幕里边的,都是在构造函数里边 3.绘…...
测试-BUG篇
文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办(高频考题) 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 BUG bug的概念 是指计算机程序中存在的一个错误(error)、缺陷(flaw)、疏忽(mista…...
vue2中 vue-count-to组件让数字从某个数字动态的显示到某个数字(后附vue3的用法)
1、首先安装 npm install vue-count-to2、使用 2.1、先导入组件 import countTo from ‘vue-count-to’2.2、注册组件 components: { countTo },2.3、使用组件 <countTo> <template><div class"home"><countTo class"count-to&qu…...
AI模型部署初认识
AI部署这个词儿大家肯定不陌生,可能有些小伙伴还不是很清楚这个是干嘛的,但总归是耳熟能详了。 近些年来,在深度学习算法已经足够卷卷卷之后,深度学习的另一个偏向于工程的方向–部署工业落地,才开始被谈论的多了起来…...
在线生成论文的网站有哪些?分享5款AI一键原创论文免费网站
一、千笔-AIPasspaper 千笔-AIPasspaper是一款备受推荐的AI写作助手,它集成了多种功能,包括论文大纲生成、内容填充、文献引用和查重修改等。这款工具基于最新的自然语言处理技术,能够帮助用户快速生成高质量的论文内容。 AI论文࿰…...
考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)
考研论坛平台小程序 目录 基于java和微信小程序的考研论坛平台小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂…...
Pandas 时间序列处理
Pandas 时间序列处理 说明: 请回答以下问题,以展示您对 pandas 中时间序列处理的全面理解。请在适用时提供代码示例。 问题 1 如何将日期字符串列表 [2023-01-01, 2023-01-02, 2023-01-03] 转换为 pandas 的 DatetimeIndex? 问题 2 给定一…...
PCL 1.8.1 + VTK 1.8.0 + QT5.14.2+ VS2017 环境搭建
先看看效果: PCL 1.8.1下载安装: Tags PointCloudLibrary/pcl GitHub 安装完成后: 如果VTK想重新编译的,可以看我的这篇博客:...
微信小程序和抖音小程序的分享和广告接入代码
开发完成小程序或者小游戏之后,我们为什么要接入分享和广告视频功能,主要原因有以下几个方面。 微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因: 用户获取与增长:分享功能可以帮助用户将小程序内容传播给更多人&…...
中断系统的原理
一、介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的。中断是指CPU在正常运行程序时,由于内部或外部事件的发生,导致CPU中断当前运行的程序,转而去执行其他程序的过程。 中断可以是硬件产生的,也可以是…...
安装Rust
Rust 是一种系统级编程语言,旨在提供高性能和内存安全,同时避免常见的编程错误。 由 Mozilla Research 推出,Rust 自推出以来因其独特的设计理念和强大的功能而在开发者社区中迅速获得了广泛的关注和采用。 curl --proto ‘https’ --tlsv1.2…...
vite学习教程05、vite+vue2构建本地 SVG 图标
文章目录 前言一、构建本地SVG图标详细步骤1、安装开发依赖2、配置vite2.1、配置vite.config.js2.2、封装vite引入插件脚本 解决报错:can not find package fast-glob imported 二、实际应用应用1:未封装,直接vue应用应用2:封装vu…...
机器学习——自监督学习与无监督学习
# 机器学习中的自监督学习与无监督学习 在机器学习的世界中,监督学习、无监督学习和自监督学习都是重要的学习方法。本文将聚焦于自监督学习与无监督学习,探讨它们的原理、应用场景以及技术细节,并通过大量代码示例来揭示这些方法的内在工作…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...
