我们平时能看到很多简历,写就是秒杀,问就是高并发。结果面试官一问 Qps 多少、响应时间多少、能抗住多大并发量,却支支吾吾说不出来。没有进行测试的接口又怎么能称为高并发呢?
这次以黑马点评的优惠券秒杀为例,我们通过 jmeter 来进行秒杀接口的压测:
新建测试计划
添加线程组模拟用户
这里我们设置线程组数量为 1000,可以自行设置。

添加 http 请求:

配置基本信息,点评秒杀业务为例

获取登录的 authorization
这一步非常重要,因为优惠券秒杀本来就是专为已登录的用户提供的,所以这里需要在每次的 http 请求头携带 token。这个数据可以在前端登录黑马点评后从右键检查选择 Internet 抓取到 autohrization。
需要注意的是每次登陆都会重新生成,也就是需要重新填写。

聚合报告
开启聚合报告,聚合报告如图包含本次测试的异常率以及 qps 等信息。
目前这个图只是为了演示,到当前步骤请先不要启动线程。

问题排查
验证测试结果,查库存查看库存是否为 0,以及订单数目是否为 100。

结果一查,只有一个订单,库存还剩 99。
为什么呢?这倒是没有超卖,反而卖不出去了?
其实在黑马点评的视频中有过这块的演示,当时是因为使用乐观锁防止超卖导致了同样结果,就是大量线程失败,而且库存未扣减至 0。
乐观锁导致库存扣减失败请看
【从零开始学习Redis】如何设计一个秒杀业务_redis抢锁-CSDN博客
在当前测试中出现这种情况的原因是虽然是 1000 个线程同时启动,但是他们用的同一个 token,所以相当于同一个用户的 1000 个分身在抢,只会有一个抢到。
解决办法就是将 lua 脚本验证一人一单的逻辑注释掉,一人下多单,让一个人模拟多个用户。否则就需要注册一千个账号,获取 1000 个 token。
解决了这个问题,我们接着往下看。
第二次压测
清空 jmeter 数据,重新启动线程组。

但是检查结果树发现大量请求 response 库存不足。
查数据库库存还有四个,为什么就说库存不足了呢?

我们回想一下秒杀业务的实现过程,为了提高并发量,采用了 redis 的 lua 做库存扣减、校验一人一单。而且我们在之前秒杀之前需要做什么?
**缓存预热!**这就与业务流程结合起来了。
我使用reids做的缓存预热,在前几次测试时候已经把 redis 库存扣减了 4,没有恢复库存。但是现在测试结束后,我们查的是数据库的库存,我们把数据库的库存设为了100,但 lua 查的 redis 认为库存没了(redis 中只有 96),但其实 MySQL 中只扣了 redis 的库存大小的数量,所以必须在每次进行秒杀活动前重新进行缓存预热。

为了验证是否是这个问题,我再次进行压测,还是 1000 个线程,如果全部失败,那么证明猜想正确。

因为这块默认情况下,异常率测试是根据请求失败的数量计算的异常率,我们想看的是请求成功的条件下业务失败的数目。所以我们可以使用 json 断言


因为我们的响应数据是如上图的 json 格式,所以我们可以根据 success 是否为 true,表示如果为 true,那么就成功,否则失败。
第三次压测
清空数据,缓存预热,恢复库存,删除订单,重新测试。

符合预期,90%的异常率,100 个优惠券并未发生超卖。但是这里注意,异常率 90%并不是请求失败了。而是我们本来就是设置 1000 个线程抢 100 个券,最多就成功 100 个,表示 900 个都没抢到,所以异常率 90%。
而这也只是简单测试,并没有展开,如果展开还会涉及到代码优化,需要监控JVM、数据库、以及CPU,然后找出性能瓶颈在哪,道阻且长。个人分析绝对是比单纯实现接口有价值得多。
关注我,带你了解更多计算机知识。