性能测试五步法

引言

 

很多做性能测试的同学都问过我这样一个问题:你说性能测试的重点是什么?

 

我的回答很简单:瓶颈分析与问题定位。


 

在性能项目的整个周期,不管是脚本设计、脚本编写还是脚本执行,都还算简单。

 

难点在于如何定位瓶颈、分析瓶颈、解决瓶颈。

 

如果你不会性能分析,脚本设计得再好,脚本编写得再完美,分析不出问题所在,那都是白白浪费时间。

 

所以,这一讲,我们来学习:如何进行性能分析,学会了性能分析的思路,才能定位问题、分析问题,从而解决问题。

 

在性能项目中,我总结的性能分析思路,分5个模块,即性能分析5部曲,如下:

1、判断性能瓶颈

2、线程递增策略

3、性能衰减过程

4、拆分响应时间

5、构建分析决策tree

 

接下来,我就对这5部曲进行一一解释。

 

判断性能瓶颈

 

如何判断性能瓶颈,在整个性能测试过程中,这是让性能测试工程最苦恼的事情。如果无法准确的定位到性能瓶颈,那么对开发的协助能力就有限,从而无法快速的解决性能瓶颈。

 

而分析性能瓶颈,也是排查解决问题的第一步。如何进行问题分析,我先上一张图:

 

 

 

通过这张图,我们很直观的知道:这是一个很明显阶梯式增加的场景。

 

但是,请思考一下,我们是否能判断出拐点在哪呢(在性能测试过程中,都是要先找拐点,再定位问题)?

 

这时候肯定就会有人说在1300左右, 也有人认为在1500左右,还有人会说这明明就是在2000出现的拐点。

 

别着急,我们再看这张TPS图对应的ResponseTime(后面简称为RT)图:

 

 

 

看到RT图,是不是就会有人说在4.5就出现了拐点。其实以上这些对拐点的判断,都不合理(不能说完全不正确)。

 

如果要对TPS的增加控制非常准确的话,就需要找到TPS在增加时,那个明显而清晰的弧度,而不那个明显而清晰的拐点,这一定要注意,也是一定要记住。

 

但是,通过TPS图和RT图,我们还是可以判断出瓶颈在第二个压力阶段就已经出现了。

 

原因

 

响应时间增加了,TPS却没有增加的那么多,到第三阶梯时,TPS增加的就更少了,响应时间还在不断的增加。

 

所以,性能瓶颈就在不断的加剧,而越往后面的阶梯,这种现象就越明显,直到系统垮掉或手动停止掉。

 

根据上面的现象,我们的判断结果:

  • 系统有瓶颈

  • 瓶颈和压力有关

  • 压力呈阶梯型,而且增长幅度在不断衰减

 

我们再来看一张图:

 

 

 

通过这个图,是不是感觉系统系统有瓶颈了。

但是,思考一个问题:瓶颈点是否跟压力大小有关呢?

 

答案:肯定不是跟压力大小有关。

 

因为通过图可以看出:

  • 这个问题是很有规律的;

     

  • TPS周期性的出现降低,并且最大的TPS也都差不多是一致的。

 

所以,即使压力降低,最多只是降低最大的TPS水位,这种情况只是让问题出现的更晚一点,但不会不出现的。

 

根据以上综述,我通过一个示意图来表示TPS的衰减过程,如下:

 

 

 

通过上图,我们可以总结出两点内容,即:

  • 随着用户数的增加,响应时间在缓慢增加;

     

  • TPS增加幅度在变缓,直到逐渐变平。

 

在这种趋势图中,我们无法看到明确的拐点,但我们却可以得出明确的结论:系统有瓶颈。

 

而系统的瓶颈又在哪里呢?通过这个趋势图,我们无法判定。

 

所以,通过TPS曲线图,我们可以知道:

  • 当前测试系统是否有瓶颈;

  • 瓶颈和压力是否有关系。

 

再强调一次

 

判断瓶颈是否与压力有关,就看随着压力的增加,TPS的变化情况,如果随着压力的增加,TPS逐渐变缓,直到拉平,那么就是有关系,否则,就跟压力没有关系。

 

这一点,一定要牢记,这是判断压力与瓶颈关系最直接的方式。

 

线程递增策略

 

接下来,我们就来说一说线程递增策略。

 

首先,我直接通过两个场景的执行结果(线程图、TPS图、响应时间图)进行对比:

 

场景一

 

 

 

线程图

 

 

 

TPS图

 

响应时间图,如下:

 

 

响应时间图

 

场景二

 

 

 

线程图

 

 

 

TPS图

 

 

 

响应时间图

 

场景一与场景二的对比情况,表格统计如下:

 

 

 

根据这两个场景的对比情况,可以直观的看出:虽然两个场景的TPS都达到了400,但是由于递增策略的不同(场景一为一次性并发500, 场景二为 连续逐步递增直到500),故产生的响应时间就不同。

 

这两个场景虽然错误率都为0,但是场景一却不符合真实的业务场景(如果你说场景一是为秒杀场景设置,那我只能稍后再解释),原因如下:

1、正常情况响应时间是从低到高的,但是在场景一却恰恰相反;

 

2、线程数是需要连续递增的,在场景一中却没有;

 

3、虽然两个场景的TPS都达到400,但是场景一的线程数却是500,而场景二的线程数40就达到了。

 

所以,我们可以总结出:对于一个系统来说,如果是仅仅改变压力策略(其他环境、资源等都不变),那么系统最大TPS的上限值就是固定的。

 

我们再回来说场景一的一次性发送500线程并发的问题:在我们常规认知里,一直觉得秒杀场景就是要最大的并发线程数,其实这种情况,并不合理。

 

因为即使线程数增加的再多,对于已经达到TPS上限的系统来说,除了RT不断的增加,其他没有任何意义。

 

敲黑板

 

我们描述系统的容量是用系统当前处理业务量,而不是线程数。

 

所以,对于场景中线程递增策略,我们要做到以下几点:

1、场景中的线程数一定是要连续的、递增的;

 

2、场景中的线程递增一定要跟TPS的递增比例有关系,而不是直接达到上限值;

 

3、针对秒杀类场景,我们前期需要做好系统预热,在预热之后,再对线程数突然增加而产生的压力,就在可处理的范围内。

 

性能衰减过程

 

在前两节中,我们了解了如何判断性能瓶颈,又知道了如何进行场景线程递增策略,那么,接下来我们就要掌握在性能测试过程中,如何判断性能衰减过程。

 

同样,我先上一个压力工具测试结果图:

 

 

 

针对上面的压力结果,我们来做三次计算:

1、当线程数达到24时,TPS为1810.6,即每秒发出的请求数为1810.6 / 24 ≈ 75.44;

 

2、当线程数达到72时,TPS为4375.1,即每秒发出的请求数为4375.1 / 72 ≈ 60.77;

 

3、当线程数达到137时,TPS为5034,即每秒发出的请求数为5034 / 137 ≈ 36.74。

 

最后,我们可以得出:随着线程数的增加,每秒的请求数却在变少,但是TPS却是在增加。

 

但是,我们仔细看这个结果可以发现,在整个压力过程中,性能是在不断的衰减的。

 

这个时候,你可能会说:你不是说了,线程数不断的增加,TPS也在不断的增加,怎么能说性能在衰减呢?

 

我再把压测结果对应的RT、TPS、线程数、每秒请求数图都展示出来,你可能就能明白了。

 

 

 

这个时候,我们在仔细看统计图,可以发现每秒的请求数下降到56左右时候,TPS就达到了上限值(即5000),再继续增加线程数,最后的结果只是响应时间不断的增加而已。

 

当然, 这里还是需要你记住:只要“线程/秒”的TPS开始变少,就意味着性能瓶颈出现了。但是,并不是说出现瓶颈了,服务器的处理能力就变差了,而是TPS仍然会上升,在性能不断的进行衰减过程中,TPS会达到上限值。

 

如果按照这样的推理,那么是不是应该在性能衰减到TPS达到最大值时,停止脚本执行呢?

 

这个并不绝对,因为是否停止继续执行,需要取决于我们的测试目的:

1、如果我们只想测试最大TPS上限值,而这个时候,就可以停止;

 

2、如果想测试系统最大运行时间,那么这个时候,就不能停止。

 

当然,还有一个场景,也是不能停止的,这里我要单独例举:如果我们想更精准的找到性能瓶颈,这个时候也不能停,因为我们要延长响应时间,从而拆分响应时间,找到性能瓶颈。

 

这就进入到了接下来我要说的:拆分响应时间。

 

拆分响应时间

 

在性能工程中,性能分析是必不可少的,而在性能分析中,拆分响应时间又是必不可少的。

 

在整个性能场景中,只要达到系统瓶颈,不管再怎么增加压力,最后肯定会导致响应时间的增加,直到出现Timeout。

 

在压力工具(Jmeter/Loadrunner/Loust……)中看到的响应时间,都是经过后端的每一个系统的。

 

这个时候,我们肯定会问到,如何能准确的判断出瓶颈点呢?

 

这就是判断的难点,但是也不要着急,因为没有解决不了的问题。

 

我先上一张图,来看一下压力测试逻辑:

 

 

 

上图,就是一个最简单的压力测试逻辑图,一个应用、一个DB,最后竟然还是拆出了8个时间段,而这还没有对压力工具自己消耗的时间进行拆分。

 

俗话说:理想总是丰满的,现实却是悲伤的。在实际的场景中,如果是内网,那么就是下面这个逻辑了:

 

 

 

而在这样的压力逻辑图,依然可以拆出8个时间段,类似于上个拆分响应时间时间的方法,这里就不拆分了。

 

当然了,还有第三种情况:

 

 

 

这种情况,我们可以更直观更清晰的拆分响应时间的。

 

拆分步骤/方法如下:

1、先去Nginx上查看时间

2、再去Tomcat上查看时间

3、最后查看MySQL的消耗

4、通过花费时间进行对比,就可以分析出是哪个环节的瓶颈了

 

这就是拆分响应时间的步骤,一步一步的来拆分,如果拆分的不准确,或者盲目的拆分时间,最后就无法准确的构建分析决策tree。

 

为什么这么说呢, 接着往下看。

 

构建分析决策tree

 

关于性能分析决策tree的重要性,我在线上/线下培训时、全链路压测专栏、亦或者在工作中都有提说到。

 

因为性能分析决策tree是性能分析环节中不可缺少的一环节。性能分析决策tree是对架构的梳理,是对系统的梳理,是对问题的梳理,是对分析思路的梳理。

 

或许你会问,性能分析决策tree有这么厉害吗?我把性能分析决策tree流程图画出来,你就知道到底厉不厉害了:

 

 

 

通过上图,我们可以直接看到,只要知道TPS、RT和错误率三条曲线,就可以明确的判断出性能瓶颈是否存在。

 

再通过性能分析决策tree,结合各个监控,就会知道是哪个环节出现的问题。这里,我在针对操作系统进行详细拆分,其余的这里就不进行拆分了。

 

看到这个流程图,是不是恍然大悟,终于知道了如何对操作系统进行拆分了。但是还是的说,前提:拆分操作系统,就需要对操作系统有足够的的了解,否则你懂的……。

 

总结

 

看到这里,性能分析5部曲就讲完了。

 

而在这一讲中,我从 性能瓶颈的判断→线程递增的策略→性能衰减过程→响应时间的拆分→分析决策tree的构建 都进行了详细的说明。

 

之所以花费这么多时间与精力来写性能分析的思路,是因为性能分析在整个性能测试过程中太重要了。

 

如果无法分析性能问题,就无法定位到问题,从而就无法解决性能瓶颈,这都是环环相扣的,缺一不可。

 

同时,性能分析也是拉开性能测试工程师level的一个重要标准。

 

性能分析在性能测试过程中是必不可少的环节。

所以,学会性能分析,是作为性能测试工程师必须要掌握的技能。

 

但是在整个性能测试行情中,据我了解很多性能测试工程师都觉得只要自己会:设计脚本、执行脚本、最后再编写一个测试报告就完事了。

 

这是不可取了,也恰恰误导了性能测试工程师的职责。

 

所以,你要学会性能分析这5部曲,让自己在跟开发/需求的同学进行沟(hu)通(qia)时,可以底气十足。

posted @ 2022-11-07 15:09  AlamZ  阅读(320)  评论(0编辑  收藏  举报