【高性能】Web性能压力测试JMeter、测试秒杀Red

高性能问题


Web性能测试 解决方案: JMeter 【不是代码单元,而是场景】


依靠JMH可以完成基本的性能测试,进行代码优化,比如在JVM预热情况下,使用Lambda、Stream比增强for 效率高;

在BS架构流行的当下,需要对场景进行性能测试,比如登录场景,商品购买,支付场景等: 常见的问题:

  • 秒杀系统最多可以抗住多大的流量不出现异常?
  • 连续100小时以上的疲劳测试是否会让系统内存无法下降,GC无法回收内存,CPU不降低?
  • 高并发压力下,应用程序哪里消耗资源最多,需要优化?
  • 针对协议的测试: 比如之前的聊天服务,HTTP轮询 和 WebSocket谁更消耗性能?相差多少?
  • 单台压力机无法生成更大压力,如何增加压力机?

JMeter web性能测试

上面的问题针对的都是web应用,也就是会进行浏览器的访问,都可以依靠性能测试工具—JMeter; 桌面GUI可以允许用户无代码编写脚本,通过后台启动JMeter的方式允许脚本,测试的是场景,而不是JMH的代码单元; (单元 — 集成);

JMeter项目整体测试,JMH代码局部测试优化

  • 下载 安装

直接到官网下载压缩包即可: Apache JMeter - Download Apache JMeter ,Cfeng的JDK为10以上版本,选用的JMeter为5.4.3, 5.3版本出现了一些奇怪的问题

下载之后解压安装, 进入bin目录,点击jmeter.sh就可以允许cmd窗口打开GUI程序,cmd窗口不能关闭

这里可以直接在查看高级系统变量位置将环境变量配置上 ---- 也就是安装目录的bin配置到path中即可,这样可以直接在cmd窗口输入jmeter就可以启动

JMeter可以对多种协议进行测试: 比如常用的http、https、ws、wss、tcp、udp、ftp等以及对NoSQL、MySQL、JMS等数据源进行性能测试

可以直接编写性能测试脚本,也可以通过脚本录制的方式进行性能测试 ---- 网页代理进行页面上的操作,操作流程被录制生成性能测试脚本

JMeter配置原件

Jmeter完成压力测试需要借助各种配置原件,完成一个最简单的抢红包测试,需要借助Http请求的Sampler、查看结果树的Listener、CSV配置辅助的 config Element

取样器 Sampler

基础单元, 各种协议的请求都是由取样器发起的。 比如HTTP请求、FTP请求、JMS发布订阅、Java请求、JDBC请求、TCB请求等、SMTP请求

在这里插入图片描述

当然最常用的还是HTTP Request,在其中配置相关的host、port、contextPath、encoding等信息 以及配置相关的请求参数, 请求参数可以使用CSV文件进行指定变量; ${XXX}即可引入文件的数据

配置原件 config Element

主要对上面取样器的各种请求进行辅助配置

在这里插入图片描述

配合取样器的HTTP信息头管理器 Http Header Manager、缓存管理器 Http cache manager、 Cookie管理器、JDBC connection Configuration 连接配置、 LDAP Extended Request Defaults LDAP扩展请求,…

逻辑控制器 Logic Controller

主要控制JMeter脚本的执行顺序, 比如从接口请求得到结果,经过逻辑Controller判断之后,执行接口2等, 灵活度更高,包括if控制器、 事务、循环、While、ForEach、仅一次、吞吐量、Switch等

前置处理器 Pre-Processor

执行取样器前,执行前置处理器,最简单的就是执行Http访问请求前需要 执行的前置处理, 比如HTML链接处理器、HTML URL重写修饰符和取样器超时等

后置处理器 Post-Processor

执行取样器后,执行后置处理器,后置处理器包括CSS/JQuery提取器、JSON提取器、边界提取器、BeanShell断言和正则表达式提取器等, 在提取数据后,可以对上个请求的结果参数化,传输到下一个请求中

断言 Assertion

断言可以验证服务器返回的数据和预期是否相符,如果不相符,可以记录或者停止测试计划,【可以类比SpringBoot自动化测试的断言】,包括响应断言、JSON、大小、HTML、XML、BeanShell

定时器 Timer

测试计划执行过程中,定时器减缓线程的运行,eg: 线程在请求接口1执行之后,需要暂停若干ms后请求2,包括固定、随机的定时器

监听器 Listener

监听器主要收集测试结果报告, 主要包括: 查看结果树、断言结果、聚合报告、若有插件: 还可以监听被测试端的CPU和内存

JMeter参数化

Jmeter的参数化实现方式包括函数、外部文件、提取的上一个接口的数据

JMeter提取数据后,在HTTP请求脚本中通过${变量名称} 使用配置的参数,除请求body外,任何地方都可以使用变量、路径、服务器名称或者IP、端口、协议编码

JMeter函数

JMeter函数可以通过函数生成相关的数据供发起HTTP请求

在这里插入图片描述

通过这个GUI界面 --》 打开Tools工具 —> 选择Function Helper Dialog 函数助手对话框

在这里面可以选择BeanShell、或者Random随机数字、RandomString随机字符串、Random随机时间、splt字符串拆分、property自定义数值、UUID和char等

如果上面选择RandomString, 拷贝粘贴字符串位置写 ** R a n d o m S t r i n g ( 16 C f e n g 123 ) ∗ ∗ , 在前面的 i n p u t 中输入数据,点击 G e n e r a t e 就可以随机生成,赋值生成的函数,就可以生成,也就是上面的 {_RandomString(16Cfeng123)}**, 在前面的input中输入数据, 点击Generate就可以随机生成,赋值生成的函数,就可以生成, 也就是上面的 RandomString(16Cfeng123),在前面的input中输入数据,点击Generate就可以随机生成,赋值生成的函数,就可以生成,也就是上面的{XXX} ---- 引入变量

JMeter读取外部文件

JMeter是可以读取外部的CSV文件的,直接新建一个CSV文件, 在线程组中添加CSV配置原件

在这里插入图片描述

使用变量主要的是指定变量,JMeter函数input中生成,而这里的CSV文件,需要在这里配置CSV文件中数据的变量的名称,在HTTP请求脚本中通过${}引用

JMeter提取上个接口数据

在JSON计划中添加JSON提取器,编写JSON提取器的相应规则,在Names of created variables后面配置HTTP请求中编写的变量名称, 在JSON path expressions 中填写JSON的value映射 eg: name --> $.name

JMeter 实战 — 测试高并发抢红包

JMeter是支持选择语言的 ---- Options -》 ChooseLanguage —> Chinese(Simplified),修改语言

首先直接新建一个测试计划,命名之后; 在测试计划下面新建线程组,设置线程数、 Rame-up时间; 这里Cfeng直接设置1s内执行1000个线程 ---- 这样才符合高并发要求

  • 线程数: 此次测试总共开启的线程数(一次访问就是一个线程)
  • Ramp-up: 表示在多少时间开启所有的线程数,如果设置时间过长,可能导致刚启动请求压力不足,不符合预期; 过短则可能导致压力过大,服务器崩溃,比如设置总现场数的10%
  • 循环次数: 整体线程组的循环执行次数, 请求事务总数 = 线程数 * 循环系数
  • 调度器: 配合循环次数和永远 同时使用,即不按照循环次数进行执行,而是根据时间循环所有线程,总事务数没有预期

之后就是在线程组下面添加HTTP请求取样器

在这里插入图片描述

HTTP取样器的使用和PostMan没有太大的差别; 这里应该是在该请求下添加查看结果树和CSV文件设置

当时Cfegn直接放在线程组下面,因为只是测试一个接口,所以影响不大,配置完成之后,点击运行即可

在这里插入图片描述

可以看到这里就成功发起1000次请求,因为Cfeng让这些请求访问的是缓存并且加上了分布式🔒,所以最终结果符合预期,只有10个人抢到了红包

测试的之前的结果,1s发起了1000次请求【来自15个用户左右】,一个用户点击多次,因为秒杀,实际一个用户会点击很多次,加了分布式锁再配合原子命令实现实现类抢红包的操作,可以看到这里能够抗住压力,是因为操作的都是在缓存中,总共的写入数据库的操作一共就10次,并且设置了为异步方式, 不需要每次都访问数据库

1s内所有的红包都抢光了,所以最后日志打印读取total的数据都是0,因为不同的用户的进程都同时进入了Service

2022-09-13 22:50:25.780  WARN 22864 --- [         task-7] c.a.druid.pool.DruidAbstractDataSource   : discard long time none received connection. , jdbcUrl : jdbc:mysql://localhost:3306/db_middleware?useUnicode=true&characterEncoding=utf-8&useSSL=true&servertimezone=GMT%2B8, version : 1.2.8, lastPacketReceivedIdleMillis : 113460
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-33] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10025 key=redis:red:packet:10011:52103535738800 金额=0.64
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-20] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10030 key=redis:red:packet:10011:52103535738800 金额=0.31
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-52] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10026 key=redis:red:packet:10011:52103535738800 金额=0.78
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-57] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10011 key=redis:red:packet:10011:52103535738800 金额=1.07
2022-09-13 22:50:25.783  INFO 22864 --- [nio-8081-exec-7] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10015 key=redis:red:packet:10011:52103535738800 金额=1.9
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-26] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10016 key=redis:red:packet:10011:52103535738800 金额=1.57
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-53] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10013 key=redis:red:packet:10011:52103535738800 金额=1.06
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-56] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10021 key=redis:red:packet:10011:52103535738800 金额=0.51
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-68] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10020 key=redis:red:packet:10011:52103535738800 金额=0.55
2022-09-13 22:50:25.783  INFO 22864 --- [io-8081-exec-65] c.server.service.impl.RedServiceImpl     : 当前用户抢到红包了:剩余红包数量:0,userId=10028 key=redis:red:packet:10011:52103535738800 金额=1.61

录制性能测试脚本

通过页面单击的形式,记录所有的请求信息,包括HTTP响应信息和请求头

通常使用JMeter的HTTP代理服务器录制性能测试脚本,【除此之外,还可以使用BadBoy工具仅录制,录制为jmx文件

测试计划 --> 添加 --> 非测试原件 —> HTTP代理服务器

在这里插入图片描述

在代理服务器中可以编写自定义的代理端口号,在目标控制器进行配置,目标控制器代表此次录制的脚本放置在哪个线程组中,配置结束,点击启动按钮即可

搭建代理服务器后,配置本地计算机的Internet属性: 增加代理服务器、刚自定义端口号

在这里插入图片描述

代理服务器进行请求的接口已经录制到线程组中

最开始问题的advise:

  • 编写JMeter脚本,一台JMeter模拟正常用户正使用,另外模拟JMeter登录,模拟登录的JMeter性能提高,得到的JMeter报表就是当前应用程序可承受最大压力
  • 测试将JMeter压力开到最大,监控秒杀系统的CPU和内存是否异常,定时检查不同数据源的的数据的一致性(mysql、redis),可得出秒杀系统最大压力
  • 服务器不断运行: 查看JVM的GC信息、CPU和内存,确保程序长时间运行,可以将使用的内存正常回收 ---- 检测是否可以长期运行
  • 使用Arthas工具、监控当前测试端口,了解线程消耗: 比如使用Redison操作Redis,查看Redisson实际开启了多少个线程,每个线程消耗的CPU和内存,查看哪个接口的响应速度最慢
  • 使用JMeter脚本录制方式,通过网络代理仿照正常用户获得JMeter脚本,只需要调整参数即可
  • 通过JMeter插件可以完成不同协议测试,使用即可; 当单台JMeter无法增加更大压力,可以部署JMeter集群💙
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值