【黑马点评】使用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 将用户登录逻辑修改回去

取消验证码检测的注释。在这里插入图片描述

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

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

相关文章

地图可视化的艺术:深入比较Mapbox、OpenLayers、Leaflet和Cesium,不同场景下应如何选择地图库

目录 地图可视化的艺术&#xff1a;深入比较Mapbox、OpenLayers、Leaflet和Cesium 一、总览 二、定制地图美学的先行者——Mapbox 1、主要功能特点 2、开源情况 3、市场与应用人群 4、安装与基础使用代码 三、开源GIS地图库的全能王——OpenLayers 1、主要功能特点 2…

rabbitmq消费者应答模式

1.应答模式 RabbitMQ 中的消息应答模式主要包括两种&#xff1a;自动应答&#xff08;Automatic Acknowledgement&#xff09;和手动应答&#xff08;Manual Acknowledgement&#xff09;。 自动应答&#xff1a; 不在乎消费者对消息处理是否成功&#xff0c;都会告诉队列删…

ComfyUI增强图像细节只需要一个节点(附工作流),SD1.5、SDXL、FLUX.1 全支持,简单好用!

今天给小伙伴们介绍一个非常简单&#xff0c;但又相当好使的一个插件。 功能很简单&#xff0c;就是增加或者减少图像的细节&#xff0c;节点也很简单&#xff0c;就一个节点&#xff0c;只需要嵌入我们的 ComfyUI 的基础工作流中就可以了&#xff0c;随插随用。 而且该插件不…

springboot mail:如何高效管理邮件服务?

springboot mail发邮件教程&#xff1f;怎么实现spring发信功能&#xff1f; SpringBoot Mail作为Spring Boot框架的一部分&#xff0c;提供了一种简单而强大的方式来集成和管理邮件服务。AokSend将探讨如何高效地使用SpringBoot Mail来管理邮件服务&#xff0c;确保邮件发送的…

Qt实现Halcon窗口显示当前图片坐标

一、前言 Halcon加载图片的窗口&#xff0c;不仅能放大和缩小图片&#xff0c;还可以按住Ctrl键显示鼠标下的灰度值&#xff0c;这种方式很方便我们分析缺陷的灰度和对比度。 二、实现方式 ① 创建显示坐标和灰度的widget窗口 下图的是widget部件&#xff0c;使用了4个label控…

二项式定理学习

1.二项式定理 这个就是二项式定理的重要公式&#xff0c;我们的二项式定理的每一项的系数&#xff0c;代表的意思为从n个里面选出k个 &#xff0c;以下是来自于百度百科上面的解释&#xff08;原谅我实在不会数学定义&#xff09; 因此我们可以去讨论二项式定理中的最特殊的一种…

深入解析LlamaIndex Workflows【下篇】:实现ReAct模式AI智能体的新方法

之前我们介绍了来自LLM开发框架LlamaIndex的新特性&#xff1a;Workflows&#xff0c;一种事件驱动、用于构建复杂AI工作流应用的新方法&#xff08;参考&#xff1a;[深入解析LlamaIndex Workflows&#xff1a;构建复杂RAG与智能体工作流的新利器【上篇】]。在本篇中&#xff…

如何自制无人机?

自制无人机是一个既有趣又富有挑战性的项目&#xff0c;它涉及到电子工程、机械工程和航空航天工程等多个领域的知识。以下是一个基本的自制无人机制作步骤和所需材料概览&#xff0c;供您参考&#xff1a; 一、准备阶段 1. 明确目标 - 确定无人机的用途&#xff08;如航拍、…

基于SSM框架和Layui的学院课程安排系统的设计与实现(源码+定制+定制)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Element UI教程:如何将Radio单选框的圆框改为方框

大家好&#xff0c;今天给大家带来一篇关于Element UI的使用技巧。在项目中&#xff0c;我们经常会用到Radio单选框组件&#xff0c;默认情况下&#xff0c;Radio单选框的样式是圆框。但有时候&#xff0c;为了满足设计需求&#xff0c;我们需要将圆框改为方框&#xff0c;如下…

SkyWalking 自定义链路追踪

对项目中的业务方法&#xff0c;实现链路追踪&#xff0c;方便我们排查问题 引入依赖 <!‐‐ SkyWalking 工具类 ‐‐> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm‐toolkit‐trace</artifactId> <vers…

【算法】博弈论(C/C++)

个人主页&#xff1a;摆烂小白敲代码 创作领域&#xff1a;算法、C/C 持续更新算法领域的文章&#xff0c;让博主在您的算法之路上祝您一臂之力 欢迎各位大佬莅临我的博客&#xff0c;您的关注、点赞、收藏、评论是我持续创作最大的动力 目录 博弈论&#xff1a; 1. Grundy数…

蓝牙模块(BT04/HC05)

目录 一、介绍 二、模块原理 1.原理图与外形尺寸 2.引脚描述 3.蓝牙模块基础AT指令介绍 三、程序设计 usart3.h文件 usart3.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 BT04A是一款蓝牙低功耗&#xff08;Bluetooth Low Energy, BLE&#xff09;模块&…

继电保护之电压重动、电压并列和电压切换

实践&#xff1a;以某开关室10kV母联隔离柜为例&#xff1a; ZYQ-824为PT并列装置&#xff0c;装置内包含一系列继电器&#xff0c;用于PT重动及并列。按照装置编号原则&#xff0c;交流电压切换箱一般命名为7n。 ​下图为装置内继电器线圈部分接线&#xff1a; 下图为装置内…

Windows下的python安装教程_2024年10月最新最详细的安装指南

文章目录 前言一、下载python二、安装python三、验证环境四、配置环境变量&#xff08;可选&#xff09;总结 前言 Python 是一种广泛使用的高级编程语言&#xff0c;以其简洁易读的语法和强大的库支持而著称。无论你是初学者还是经验丰富的开发者&#xff0c;安装 Python 都是…

游戏盾是如何解决游戏行业攻击问题

随着游戏行业的迅猛发展&#xff0c;其高额的利润和激烈的市场竞争吸引了众多企业和创业者的目光。然而&#xff0c;这一行业也面临着前所未有的业务和安全挑战&#xff0c;尤其是DDoS&#xff08;分布式拒绝服务&#xff09;攻击&#xff0c;已经成为游戏行业的一大威胁。今天…

详解 SPI 机制

SPI(Service Provider Interface) 是 JDK 内置的一种服务提供发现机制&#xff1a;可以用来启用框架扩展和替换组件&#xff0c;主要用于框架中开发。例如&#xff1a;Dubbo、Spring、Common-Logging&#xff0c;JDBC 等都是采用 SPI 机制&#xff0c;针对同一接口采用不同的实…

基于SpringBoot博物馆游客预约系统【附源码】

基于SpringBoot博物馆游客预约系统 效果如下&#xff1a; 主页面 注册界面 展品信息界面 论坛交流界面 后台登陆界面 后台主界面 参观预约界面 留言板界面 研究背景 随着现代社会的快速发展和人们生活水平的提高&#xff0c;文化生活需求也在日益增加。博物馆作为传承文化、…

k8s 中的 PV 的动态供给

目录 1 存储类 Storageclass 介绍 1.1 StorageClass 说明 1.2 StorageClass 的属性 2 存储分配器 NFS Client Provisioner 2.1 官网存储分配器的部署介绍 2.2 实现动态创建 PV 模版清单文件的介绍 2.2.1 Storageclass 存储类的模版 2.2.2 创建 Provisioner 制备器的模版 2.2.3…

【Linux】文件IO系统[ 库函数 ]封装了[ 系统调用 ] +【区分文件结构体FILE和file与files_srtuct表】(读写接口盘点与介绍)

前言 大家好吖&#xff0c;欢迎来到 YY 滴Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…