性能公开课 | 为什么性能测试做完了,却不会分析?

性能公开课 | 为什么性能测试做完了,却不会分析?

Cosmos 774 2022-11-08

加的一个技术群,群里都是各位大佬,时常进行技术分享,以下是大佬分享的总结。

1、抛出问题

很多同学学会了性能测试工具的使用,但做完性能测试不会分析:不知道怎么算把性能测试做完了、怎么算测试结果达标了?我们今天就把这个问题解决一下。

分析问题成因:
我们在性能测试后期,遇到了“不会基于测试数据分析出结果”的问题,原因大概有以下3种:
1、没有明确的需求文档告诉我们,期望结果是什么,导致我们无从比较。
2、我们没有事先设计出能产生 “可分析性、可比性的数据”的测试用例,我们执行了很多性能测试,但都是盲目的,于是很多同学在问:老师,这个结果出来了,该怎么看啊? 该怎么分析啊?
3、我们事先没有列出需要监控的清单,不知道哪些数据需要收集,导致我们无从分析

这3个问题里,前2个是理论知识不够,后1个是测试基础知识和经验不足。

首先,我们需要再次同步一下性能测试的关键指标是:
1、TPS:每秒钟能同时处理多少笔交易
2、资源消耗:为了达到一个很大的处理能力,系统耗费了多少的CPU、内存、带宽
3、时间消耗:处理单个交易/请求,花费的时间是多少?毫秒级的,还是秒级的?

2、针对上述的第3个原因,公布答案如下:

要想做性能测试,至少要监控或收集以下数据:
1、系统的资源消耗情况:CPU利用率、剩余可用内存的变化情况、磁盘读写的情况、网络带宽使用的情况。
2、测试期间,任意时间点的并发用户数有多少?
3、测试期间,任意时间点的TPS是多少?(transaction per second)
4、测试期间,任意时间点任意请求的平均响应时间是多少?
5、测试期间,所有请求、交易是不是成功的,还是有失败的情况,失败率是多少?
(由于访问超时,请求处理失败导致的最终交易无法完成的问题,视为交易失败)

3、针对第1个原因,解决思路如下:

1.首先,分析这个网站的用户量有多少? 或者,应该承载多少用户?这种数据可以对比竞争对手,或者根据网站的被访问量算出。对于新开发的从未上线的系统,则请和甲方或者产品经理做充分的沟通,至少获得“正常情况下,单天的总用户量会在XXXXX左右”这样的数据。

2.再者,这些用户肯定不会24小时不停地访问我们的网站,毕竟大部分人是晚上休息,白天使用网站的。那么,这些用户在真正使用网站的时候(浓缩在白天的8个小时)每个人每天要发多少个请求?以一个用户登录,浏览商品,加入购物车,结算,支付为例,假设需要请求40个页面,发出 200个请求(请以你真实测试的网站做计算)那么,如果是10万人,在8个小时内需要发出的请求数是: 10万*200次 = 2000万, 也就是每小时250万,每分钟 41667个,每秒钟 695个。所以,我们得到了这样一个期望结果:要想网站正常运行,得扛得住每秒695个请求,如果考虑搞活动的情况(比如双十一的秒杀)那请把695 乘以 3,甚至乘以6(3和6是经验值,是非常悲观的假设了用户24小时不停歇地访问,于是在之前8小时的量级下乘以了3 ,又考虑了用户可能翻倍的情况,于是又乘以了2)。

3.上面,我们拿到了695个请求/秒 (需要乘以3或者6)这样一个期望结果,我们就可以像做功能测试那样验证实际结果是否与期望结果保持一致了。

4、针对第2个原因,正确的做法如下:

4.1 整体规范步骤:

1、设计测试用例:

a)需要对哪些功能做性能测试,施压的压力值多少合适?期望的结果是什么
b)把测试脚本里的步骤拆细一些,如果整体的平均交易响应时间高,得通过测试结果看出来具体是哪个步骤拖了后腿

2、想好执行测试期间要监控哪些指标,做好准备工作

3、执行测试、同时收集各种数据

4、结束测试,分析数据,得出结论

4.2 下面分步骤来讲:

1.设计测试用例(明确对象、目标)

压测,不要一下子直奔主题(一开始就把并发用户数猛得提升到最高):施加的压力要慢慢增大,而且每次增加压力的时间间隔要合理,每次增大压力的量级要合理。

举例:

一个企业内部的信息管理系统,假设这个企业有2000人,那么每天最多也就2000人会施压。那么设计用例如下:
image

解释一下上面的这个表格:
1)开始时,先用1个人施压,压5分钟,看看当只有一个人用系统时, 系统反应有多快?把这个值当做“标杆”,当做基准值,如果有很多人用这个系统,系统反应依然像“标杆”那么快,就非常好了。

2)然后,用10个人压, 如果10个人一压, 系统立马垮了,后面的测试的就别做了。若10个人压,观察5分钟没问题,那么才正式开始施压。

3)把用户增加到25个,压5分钟,之后,每5分钟再新增25个,一直增到200个用户。

4)最终,我们酝酿了几十分钟,才把并发用户数 提升到200。当并发用户数到达了200时,保持这个压力不变,继续施压30分钟。

为了给大家一个直观的感受,借用jmeter的图演示说明一下:从25并发开始,线程组的设置如下:目标的并发用户数是200,酝酿40分钟达到目标并发用户数,这期间分8次增加压力(每次增加25),每次增加压力的时间间隔5分钟,当最终达到200并发的压力时,保持30分钟。
image-1667878228847

上述测试用例设计中,每次变化的变量就一个,并发用户数变了。其他什么都不要变。这才能使得我们可以 比较 25个并发用户、 50个并发用户的 不同压力之下, 我们收集到的数据有什么区别。从25 到200,我们设计了7个梯度, 通过这个梯度我们可以得出: 随着并发用户的增多, 数据的变化趋势是怎样的。

但如果我们一次变化的变量有2个或多个,那么我们就不知道:当数据不一致时,是由哪个变量引起的变化,这些数据也就不具备可分析性,可比性了。
举例,下面表格的数据是不具备可比性的:
1)测试的场景不相同
2)被施压的服务器配置不同
3)施压的并发用户数不同
4)施压的时间也不同
image-1667878270855

所以,要想性能测试用例的结果可以分析、可以对比, 要保证,基于测试的目的,每次只改变一个参数:

举例1,以验证“系统是否能支撑200个并发用户”为测试目的,需要保证:

  • 变换压力时,测试的场景(工具执行的脚本)完全一致
  • 不同压力下,施压的时长完全一致(每个压力固定施压XX分钟)
  • 被施压的服务器的配置(CPU/内存/带宽/磁盘)、状态完全一致(每次施压之前,确保机器是被初始化过的,上一轮测试的压力已释放干净、上一轮测试产生的各种任务已执行完毕、 上一轮测试产生的各种占用磁盘空间的数据已清除或者挪走了)
  • 而需要变化的,就是并发用户数(设计几个有规律的梯度,比如25,50,75,100…最终达到200)
    上述测试,当我们施压到200并发后,若以下条件满足
  • 每笔交易都能正常处理(脚本里添加了检查点)
  • 平均响应时间不超过300毫秒每笔(根据实际情况调整)
  • 事务100%都处理成功
  • 系统的CPU被利用率持续在30%以内(业界规范)
  • 系统的剩余可用内存占比持续在60%以上(业界规范)
    就视为测试通过,否则不通过。

举例2,以“验证系统是否能每秒钟处理695个请求”为测试目的,需要保证:

  • 变换压力时,测试的场景(工具执行的脚本)完全一致
  • 不同TPS下,坚持的时长完全一致(每个TPS保持XX分钟无变化)
  • 被施压的服务器的配置(CPU/内存/带宽/磁盘)、状态完全一致(每次施压之前,确保机器是被初始化过的,上一轮测试的压力已释放干净、上一轮测试产生的各种任务已执行完毕、 上一轮测试产生的各种占用磁盘空间的数据已清除或者挪走了)
  • 而需要变化的,就是期望通过持续增大并发用户数,让TPS变大,最终达到695这样一个数值。而,TPS每变大一次,也要持续几分钟(要稳步增长)
    为了给大家直观的感受,继续借用jmeter,画出效果图如下:
    image-1667878466013

上述测试,当我们的TPS最终到695后,若仍以下条件满足

  • 每笔交易都能正常处理(脚本里添加了检查点)
  • 平均响应时间不超过300毫秒每笔(根据实际情况调整)
  • 事务100%都处理成功
  • 系统的CPU持续在30%以内(业界规范,根据实际情况调整)
  • 系统的剩余可用内存占比持续在60%以上(业界规范,根据实际情况调整)
    就视为测试通过,否则不通过。

2.想好要监控的指标是哪些,通过哪些工具监控,事先调试好这些工具,确认监控正常(不要着急开始测试,后补)

3.执行测试,同时收集数据(后补)

4.基于测试数据,分析出结果

有了前面的“结果可分析可比”的测试用例,执行了测试,收集了足够的数据之后,就可以分析了。
假设测试收集到的数据如下:

image-1667878503115

通过上表可以看出:
1、当并发用户数达到25时,平均交易的响应时间已经超过了我们的期望结果(300毫秒)
2、当并发用户达到100个的时候,CPU饱和了,系统无法再继续提供服务了。
3、那么本次测试的结论是:测试未通过:基于目前的环境,系统无法支持200用户并发
导致本次测试未通过的原因:
施压到75~100区间时,CPU饱和了(其他系统资源基本正常),需要进一步探查为什么CPU饱和,哪个地方对CPU依赖、消耗这么多?请开发针对这个测试结论,剖析一下代码或系统环境,看是配置的问题,还是代码的问题。

5、加深性能测试的理解

下面通过一个功能、性能测试用例设计的对比,加深大家对性能测试用例设计的理解:

1、假设,需求文档里写着:
未登录也能把商品加入购物车,当用户最终去结算的时候,先让用户登录,同时保持操作者登录前购物车里的内容不变,连同登录后该用户购物车里本来有的商品(以前在登录状态下添加到购物车里未下单的商品),在结算页一起显示给用户。

2、那么,测试人员编写的测试用例,很可能是像这样的:

image-1667878594128
image-1667878608105
3、接下来,是执行测试用例的阶段,我们只需要根据期望结果里写的验证点,一一确认,就把测试做完了。

从上面的功能测试用例设计中,我们发现了一些可以规律,可以抽取出来(每个功能测试都这样):
1、功能测试,必须有期望结果(否则无法执行)
2、我们会设计功能测试的用例,是因为我们细抠了产品的需求,逐字推敲,列举了每个需要测试的点,然后通过拆分步骤,写出了如何模拟用户操作,一步一步去验证,当出现问题,我们能知道执行到哪一步遇到了阻碍
3、为了保证测试执行的结果是有效的,我们要写清楚如何初始化测试环境(上述用例中,清除cookie)
4、为了方便对比、验证测试结果,我们做了必要的数据收集(上述用例中,截图、记录)

其实,性能测试,也完全是这样:
1、必须先搞清楚,执行这个用例后,怎么算测试通过,即性能测试用例也得有期望结果:
image-1667878683443

2、为了定位问题,我们把性能测试的脚本也拆分了步骤,让“它们彼此划清了界限”,因为每个步骤都有可能拖慢了性能,我们需要知道,当性能不佳时,到底是哪个步骤影响的。需要专门通过一课讲解,怎么拆分脚本。

3、为了保证测试结果的有效性,我们在每次重新开始测试时,要初始化环境,不要让上一次的“噪音”污染本次的测试

4、为了测试结果可分析可比较,我们要收集关键性能指标数据,否则我们真的是“巧妇难为无米之炊”

看看上面的描述,发现功能测试的4个规律,在性能测试时,完全用到了的。

好了,以上就是本次课程的内容,谢谢大家。

作者 孙磊
微信 18210226510