作者:马涛
在庞大的性能测试面前,我还是一个江湖小辈。然而在被YW大神领进门之后,性能测试中的变化莫测、十面埋伏、刚柔并济、九九归一,仿佛让自己窥见了一门武林绝学,继而心生敬畏之心。
Long Long Ago,听过YW大神对性能测试方面的分享。那个时候就感觉眼前的这个男人不明觉厉,练就了一身武林绝学,是自己以后发展的榜样。当时他还给我们展示了他的武林秘籍,是这样的:
第一次真正接触性能测试是在邮箱大师组,当时是要去对“邮件撤回”的接口进行性能测试,2017年6月25日接到任务,二话不说开始准备了起来。对jmeter速成之后,拿着wzprecall的脚本就开始开压。
那么第一个问题来了:
我:我应该怎么压?我是说有没有一个初始的值可以入手去压?...
我:YW大神经验丰富,是否可以预测出这个初始值?
YW大神:不能。
我:...
YW大神:如果我都预测出来了,那还需要性能测试做什么?
我:哦...
YW大神:两个方法:要么和产品交流拿到实际的用户量数据,要么自己想办法。
我:好嘞。
屁颠屁颠跑去找产品同学,在我的三寸不烂之舌以及一箩筐解释下,产品同学终于听懂了,但是回答是:我不知道,我真的不知道,我真的真的不知道。。。
怀着复杂的心情我翻开了YW大神的武林秘籍第一页,当时有这么一张图:
看着这本高深的武功秘籍开始发散性思维:
性能测试就像过山车,开始的慢速起步让你紧张,中途的起起伏伏让感觉很爽,最后戛然而止回到起点。
所以,性能测试中:
这里普及一下【Ramp-up Period】:
Ramp-up Period用于告知JMeter要在多长时间内建立全部的线程。
该数据默认值是0,表示JMeter将立即建立所有线程如上图图一。
假设Ramp-up Period 设置成T秒,全部线程数设置成N个,JMeter 将每隔T/N秒建立一个线程。如上图图二。
记录你被“甩”的最爽的那段时光,因为那段时光是过山车最大的意义,随后一切都是满脸激动的泪水。在性能测试中可以将90%Line作为一个重要的参考数据。
经过初探武林秘籍形成练法心得之后,开始了自己的第一层修炼,数据如下:
看到图中显示的这么多Error,发现第一次在没有高人点拨的时候,很难参悟其中奥义。但是也习得一些武功心法:
1、在以上用户量的情况下,这个性能是很差的;
2、知道了报告里面字段的意义:
1)#sample:这次测试任务中,一共发出了多少个请求
2)Average:单个request的平均响应时间
3)Median:50%用户的响应时间
4)90%Line:90%的用户一个请求的响应时间
还有Error和Throughtput以及最大、最小响应时间等。
我们这次脚本中设置的超时时间也是8000ms,所以可以看到还是有一部分请求超时,才会导致最后请求失败。
根据武侠小说的经验得出,再这样练下去肯定会走火入魔,当务之急需要YW大神指点一二,必能得其真传。
拿着上面粗糙的数据,我又去找了YW大神。
当时大神只问了一个问题,我立马打道回府干劲十足:“单线程的响应时间是多少?”
开始参悟: 当没有人坐过山车时,过山车肯定是不会开的。 但是就算只有一个人坐过山车,一段时间内,也必须开车。(当然在国内不可能)。而本文的第一张图可以看到,用户量也是从0开始增长,而单线程(1个用户)可以作为一个参考的基准。
上图可以看到一个用户的执行一次的响应时间,然后可以慢慢递增。 然后我将线程数逐渐增加的同时,有了以下的测试数据:
拿着上图手中的测试数据,说不出来的感觉,早晨测试出用户量在20~25之间似乎接近饱和,但是下午的数据基本是在30~40之间,带着疑问我又来咨询YW大神。
YW大神:你是在哪里跑的?机器的cpu如何?内存怎样?
我:...这些我有看的啊,在我本地机器跑的(顺便随手拿出了我的电脑内存和cpu数据)
YW大神:要在服务器用jmeter命令行跑。
我:哦...
认真回去看了Jmeter官方文档,第一页赫然写到:欲练此功,必先...使用命令行!
For load testing, you must run JMeter in this mode (Without the GUI) to get the optimal results from it.
这里对命令行格式的使用记录如下:
例1:测试计划与结果,都在%JMeter_Home%\bin 目录
> jmeter -n -t ../scripts/wzprecall.jmx -l result.jtl
例2:指定日志路径的:
> ./jmeter -n -t ../scripts/wzprecall.jmx -l report-output\01-result.csv -j report-output\01-result.log
【拓展】:
例3:默认分布式执行:
> jmeter -n -t ../scripts/wzprecall.jmx -r -l report-output\01-result.csv -j report-output\01-result.log
例4:指定IP分布式执行:
> jmeter -n -t ../scripts/wzprecall.jmx -R 192.168.10.25:1036 -l report-output\01-result.csv -j report-output\01-result.log
测试数据以及分析:
数据中看到: 用户量在30到40之间基本饱和, withdrawQuery请求吞吐量基本在16.5/s。
测试数据看起来已经有点样子也得到了结果,拿着数据我找了YW大神。
YW大神:吞吐20都不到,这个是不可能的。
我:...
YW大神:注意控制吞吐!
测了这么多的数据,发现很多时候的步骤都是自己不断尝试不同的线程数,在有很多未知的情况下去试探,这种方法耗时耗力,而且最后得到的数据并不能说明问题。
那么另一种方法就是完全通过定时器来控制QPS,这就类似于控制变量法,将吞吐控制之后,如果实际的吞吐达到限制的吞吐表示现在性能合理,且有上升空间,如果随着线程数的增加限制的吞吐和实际吞吐差别很大,那么恭喜你,你找到了这个接口性能的天花板中的一板。
Jmeter提供了一个非常有用的定时器,称为Constant Throughput Timer (常数吞吐量定时器),该定时器可以方便地控制给定的取样器发送请求的吞吐量。
Target throughput(in samples per minute):目标吞吐量。注意这里是每分钟发送的请求数。20 QPS ,这里的值应该是1200 。
Calculate Throughput based on :有5个选项,分别是:
This thread only :控制每个线程的吞吐量,选择这种模式时,总的吞吐量为设置的 target Throughput 乘以该线程的数量。
All active threads : 设置的target Throughput 将分配在每个活跃线程上,每个活跃线程在上一次运行结束后等待合理的时间后再次运行。活跃线程指同一时刻同时运行的线程。
All active threads in current thread group :设置的target Throughput将分配在当前线程组的每一个活跃线程上,当测试计划中只有一个线程组时,该选项和All active threads选项的效果完全相同。
All active threads (shared ):与All active threads 的选项基本相同,唯一的区别是,每个活跃线程都会在所有活跃线程上一次运行结束后等待合理的时间后再次运行。
All cative threads in current thread group (shared ):与All active threads in current thread group 基本相同,唯一的区别是,每个活跃线程都会在所有活跃线程的上一次运行结束后等待合理的时间后再次运行。
在控制吞吐之后,得到的数据有模有样:
手捧着数据,回到了YW大神身边,YW大神语重心长的说:
在我的武功秘籍里,不对,在我的ppt里有一张performance curve。
你的结果能对的上performance curve,你就能明白一些结果了。
一切仿佛又回到了起点,只是世界变得安静了。静静地翻看这本秘籍,我想我有点懂了。
最后的总结: 总结:
用户量为40的时候,平均响应时间基本在400ms左右,此时吞吐量在1500/min(25/s),吞吐量还在上升阶段。
用户量到55~65阶段,吞吐量基本达到峰值2076/min(34.6/s),用户量在65的时候,响应时间开始快速上升。
用户量在70+以后,吞吐量急速下降,相应的响应时间也在75的时候达到了1000ms+左右。
通过以上评估,压力<=40阶段,为light load阶段,压力在40~50之间比较理想饱和阶段,50~65之间服务器heavy load阶段。
当用户>70的时候,为buckle Zone阶段。
感谢YW大神循循善诱,不断的鞭策和无私奉献,最终获得这本武林秘籍,这将是我的研究方向。
感谢以下作者的妙笔生花,让我能快速看懂并练习自己的心法:
参考文献:
https://www.cnblogs.com/fnng/archive/2012/12/22/2829479.html
http://www.it610.com/article/5454639.htm
本文来自网易实践者社区,经作者马涛授权发布