软件测试最全性能测试,这些被你忽略了吗?_性能测试纵向tps扩展性,劲爆

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

目前软件开发为了提升性能,会引入各种中间件,例如:Kafka、RabbitMQ等等,这些中间件被大家广泛应用,它本身的性能也是得到了大家的认可,单机都能支持万级甚至十万级的吞吐量。于是很多人就直接拿来就用,往往问题总是出现在容易被忽略的中间件连接上。那么可以支持万级十万级的中间件,为啥还存在性能问题呢?

带着疑问,我们还是先讲一个故事:

大西北有一个李家村,村里有100户人家,整个村子都是以农耕为生,由于常年缺水,地里的庄稼收成很差,村民生活比较贫苦。距离该村子50公里外有一个天然湖泊,水量非常充足,如果可以把湖泊中的水引入到村里,就可以解决吃水的问题了。有一户比较富裕的人家,家主叫李有财,花费重金从湖泊开始铺设水管道,一直延伸到他家里,于是他家的水源问题解决了。其他村民也想效仿,但是碍于资金有限,于是村民们想到一个方案,修建一个蓄水池,将李有财家的水管直接接入蓄水池,再从蓄水池分发到各户人家了。该方案得到全村人的支持,据统计大概300立方的蓄水池就足够全村人正常用水了,于是全村筹资进行建造。蓄水池造好以后,全村傻眼了,根本没有解决吃水问题。由于上游只有一根水管,根本不足以将蓄水池装满,下游还连接着整个村子的所有住户,最后导致整个村子依然没有水。

大家知道为啥吗?难道是300立方的蓄水池太小了?不足以支撑全村人用水吗?其实最根本的原因是水管道太小了,当初的铺设只是供1户人家的使用,现在需要供全村使用,肯定是不够的。

根据上面的故事,我们把他联想到软件开发中来。中间件就像故事中的蓄水池,300立方的体积,如果蓄满水是足够全村使用的,同理,单机十万级吞吐量的中间件,本身的性能是足够支撑一个庞大的系统的,但是如果忽略了上下游的连接,就可能会导致出现严重的问题。

所以,应用了中间件的场景,一定需要考虑做性能测试,每个中间件有成百个配置项,不同的配置项也会带来不同的性能结果。中间件本身的性能可以不用考虑,但是从上游到中间件,再到下游的整个链路一定不能忽视。

四、如何开展性能测试

开展性能测试一般有以下几个步骤:确定性能需求、设计测试用例、准备测试环境及测试工具、执行测试、分析结果、性能调优、编写测试报告。

性能需求

我们先讲解第一步,如何确定性能需求?还是讲一个故事:

某货运公司提出一个需求,需要制造一辆卡车用于A城市和B城市之间的货物运输。某汽车制造商制造了一个可以载重5吨的小卡车去交付,交付现场发现货运公司需要拉的货物重达50吨。于是汽车制造商只能重新制造,20天后终于生产出了可以载重达标的货车,于是货运公司进行了验收试验,拉上货物从A城市到B城市,沿途需要经过一个陡坡,这时才发现载重50吨的货车想要爬上陡坡需要至少250匹的马力,但是该货车设计的马力只有190匹,完全不能实现从A城市到B城市的运输,只能再次重新生产。

上面这个故事我们可以看出,载重50吨、马力250匹这两个就属于性能需求。因为如果不能满足这两个性能要求,就不能帮助货运公司实现A城市和B城市之间的货物运输。那么,我们总结一下性能需求需要满足的特点:

  1. 明确需要何种测试类型

上面我们提到,性能测试包括负载测试、压力测试、峰值测试等类型。所以在做性能测试的时候,首先需要明确测试类型,不同场景需要用到不同的测试类型,不同类型的测试方法也有差异,可以选择其中一种类型或者多种类型的组合。上面的故事中需要验证车辆的最大性能拐点和长时间运输的性能效果,所以至少需要用到负载测试和峰值测试。

  1. 需要满足最低运行标准

这里不难理解,上面的故事中汽车制造商制造了三次货车才满足了货运公司最基本的运输需求,就像做软件一样,如果性能需求不足以满足客户的最低要求,只能返工重做。

  1. 需要有明确的数字支撑

作为一个性能需求,必须是明确的数字,就像载重50吨、马力250匹一样,只有约定了明确的数字才能做出合格的产品。在软件测试中,某个接口要求响应时间在200ms以内,TPS需要达到1000以上。只有明确了数字,才能更好的展开性能测试。

  1. 涉及的相关人员需要达成一致

性能需求必须保证相关人员的意见是一致的,上面的故事中货运公司和汽车制造商需要保持卡车的性能需求的同步和一致性。在软件测试中,性能需求需要从产品、研发、测试、运维等相关的人员保持一致。

那么,获取性能需求的途径都有哪些呢?

  1. 需求阶段

就像上面的故事,如果在需求阶段就充分了解了客户的性能需求,就不会返工3次。在实际工作中,一个需求到手以后,需求的提供方不能完全预估出性能的要求,但是作为技术人员需要充分了解需求,再根据需求定义出性能需求。

  1. 行业的最低标准

每个行业都会有众多的公司,每个公司一般也都会有同类的产品,如果想要在众多产品中脱颖而出,最低的标准就是不能比别人差。一旦你的响应速度比别人差很多,是很难留存用户的,根据友商的各种数据可以定义出一些性能需求。

  1. 公司内部标准

公司内部会有一套自己的性能标准。根据公司现有产品的运行数据进行分析,总结出一套公司标准的数据作为性能需求。

测试工具

在日常的软件测试工作中,最常用的性能测试工具是LoadRunner和Jmeter。

LoadRunner 是HP(Mercury)公司出品的非常有名的商业性能测试工具,支持多种协议,功能非常强大。支持脚本录制和自主编写脚本,如果想要更充分使用它的功能,对使用者的要求比较高,目前大多介绍性能测试的文章都以该工具为基础。

Jmeter 同样是非常有名的开源性能测试工具,是由Apache组织基于Java语言开发,功能也很完善。一般在介绍Jmeter的时候,都是作为接口测试工具的使用,但实际上,它是一个标准的性能测试工具。它相关的资料也非常丰富,官方文档也很完善。

另外,还有一款很好用的开源性能测试工具:wrk。也许很多人都没有听说过,他是一款轻量级性能测试工具,采用网络异步IO模型,使得系统使用很少的线程模拟大量的网络连接以增大并发量,只支持http协议类型请求,官网文档是这样描述的:

但是,雪球在做性能测试的时候,用的最多的却不是以上3款工具,而是另外一款开源性能测试工具:Locust。下面先通过一组对比简单了解一下这几款工具。

LoadRunnerJmeterwrkLocust
分布式压力支持支持不支持支持
单机并发能力
并发机制进程/线程线程线程协程
开发语言C/JavaJavaCPython
报告与分析完善简单图表简单结果简单图表
授权方式商业收费开源免费开源免费开源免费
测试脚本形式C/JavaGUICPython
资源监控支持不支持不支持不支持

根据上面的对比,我们可以看出Locust的几个特点:

  1. Locust使用Python语言开发,测试资源消耗远远小于Java语言和C语言开发,且HTTP请求完全基于 Requests库,同样可支持其他协议或者自定义请求,可拓展性强,理论上可测一切系统;

  2. Locust借助于协程实现对用户的模拟,不同其他三款使用线程数提高并发量,相同物理资源(机器cpu、内存等)配置下Locust能支持的并发用户数相比另外3款可以提升一个数量级;

  3. Locust支持分布式部署测试,能够轻松模拟百万级用户并发测试。

同样,Locust也是有很多缺点的:

  1. 不支持脚本录制,想要使用就必须自己编写测试代码,这对于不太了解代码的人来说,算是一个很高的门槛了;

  2. 不支持资源监控,想要监控资源需要借助其他监控的工具;

  3. 极简风的测试报告与分析,也是一直为人所诟病。

雪球选择Locust的主要原因,就是看中了它的这几个优点。雪球用户基数大,有些接口的QPS已经上万,刚好Locust可以满足少量测试资源即可模拟大量并发。对于它的这些缺点,都可以通过其他方式进行弥补。另外,使用Locust作为性能测试工具,还需要注意以下几个方面:

  1. 网上搜索的Locust的教程,大部分都是基于0.x的版本进行编写的,但是现在的最新版是2.x的版本,这两个版本是有很多区别的。

  2. 既然Locust是借助于协程实现并发,就会受到协程带来的一个重要的问题:失去了标准线程使用多CPU的能力,也就是说一个Locust的进程只能使用一个CPU线程的资源,如果想利用多核多线程的CPU资源,就需要同时启动多个Locust进程,就需要用到master/slave的机制。

  3. 运⾏⼤规模测试时,建议在Linux机器上执⾏此操作,因为协程在Windows下的性能很差。

执行测试

首先需要安装Python3.9+Locust2.9的环境,下面是一个简单的测试脚本:

from locust import HttpUser, TaskSet, task, between, User

classReplayAction(TaskSet):
    @task(8)defdemo(self):
        url = '/S/SH600519'
        headers = {'Content-Type': 'application/json; charset=UTF-8'}
        try:
            http_url = User.host + url
            with self.client.get(http_url, headers=headers, name=url, catch_response=True) as response:
                if response.status_code != 200:
                    response.failure("Failed")
        except Exception as e:
            print("出现异常:%s" % e)

classRePlayer(HttpUser):
    wait_time = between(0, 0)
    host = "https://xueqiu.com"
    tasks = [ReplayAction]
复制代码

ReplayAction:这里定义要压测的接口,继承TaskSet。接口用@task进行装饰,表⽰为⽤户⾏为。根据不同的性能测试需要,这里可以定义多个接口,@task括号⾥⾯参数表⽰该⾏为的执⾏权重,数值越⼤,执⾏频率越⾼,不设置默认是1。self.client调⽤get和post⽅法,和requests类似。在特定的需求下,ReplayAction可以有多个,每个ReplayAction里面装饰的权重分别计算,互相不影响。

RePlayer:继承HttpUser(老版本继承HttpLocust),⽤于设置⽣成负载的基本属性。wait_time是每个负载任务之间最小等待时间和最大等待时间(老版本需要单独设置,分别是min_wait和max_wait);tasks指向定义了用户行为的类,它是列表格式,可以有多个ReplayAction(老版本为task_set,不是列表格式,只能定义一个ReplayAction,如果想要实现多个的话,需要在ReplayAction中定义tasks,并做task嵌套来完成,如果实现了task嵌套,interrupt()在task class中必须定义,否则进来就出不去了。)

脚本编写完成以后,就需要执行脚本,雪球有专门用于执行性能测试脚本的Linux服务器。将脚本上传至服务器以后,执行以下命令:

locust -f demo.py--headless  -u 1000 -r 100 -t 3m 
复制代码

–headless:非Web UI的方式执行脚本,结果直接在命令行输出(老版本为–no-web)

-u:并发用户数(老版本为-c)

-r:每秒增加的用户数(Locust不是启动后马上就通过设定的并发用户数执行压测,而是逐渐加压,直到增加到设定的并发数为止,这个设置就是每秒加压的数量)

-t:设置运行的时间

由于Locust是借助于协程实现并发,所以通常情况需要用到分布式进行压测,分布式的主从启动脚本略有不同:

Master:

locust -f demo.py--master--headless  -u 1000 -r 100 -t 3m --expect-workers=1复制代码

Slave:

locust -f demo.py--worker--headless  -u 1000 -r 100 -t 3m --master-host=xx.xx.xx.xx复制代码

–master:表示该进程是主进程,需要优先启动主进程,启动以后主进程进入等待状态,直到连接了指定量的从进程以后才开始工作。

–expect-workers:表示等待几个从进程连接后再开始测试,从进程个数达到要求后会立即开始执行,不设置默认为1(老版本为–expect-slaves)。

–worker:表示该进程是从进程(老版本为–slave)。

–master-host:表示连接主进程的IP,不设置表示连接本机

等待程序执行完成后,命令行会显示本次执行的结果,如下:

性能结果

性能测试步骤中,还有一个环节是非常重要的,那就是分析结果环节,下面我们重点讲一下性能结果都有哪些需要注意的。

相信大家都吃过国内很出名的火锅连锁某某捞,大部分人在用餐的时候应该都需要排号等位吧,我最长一次排了近3个小时。大家有没有想过,如果一个面馆,让你排队三个小时才能吃上一碗面,你应该转头就走了,为啥某某捞就能心甘情愿的排队三个小时呢?

上面的问题先思考着,下文都简称一个餐厅,我们先做一些假设:

  1. 餐厅共有10张桌子,10个服务员,每个服务员负责服务一张桌子的客户;

  2. 每桌人用餐时间都是1小时;

  3. 顾客忍耐的最长等待时间是2小时。

当餐厅只有2桌人用餐的时候,只需要2个服务员提供服务即可,其他服务员有的在休息,有的在刷手机。1小时后,两桌客人吃完饭走了,在这一小时里整个餐厅只赚了2桌顾客的钱。

当餐厅有7桌人用餐的时候,就需要至少7个服务员提供服务,其他服务员需要临时打打杂。1小时后,这7桌客人也吃完饭走了,那么在这一小时里整个餐厅赚了7桌顾客的钱。

由于这个餐厅有10个服务员,所以当餐厅有10桌人用餐的时候,10个服务员都需要去提供服务,餐厅在这1小时里可以赚10桌顾客的钱。

通过上面的几个场景,我们可以看出,同样是一个小时,餐厅可以根据顾客的数量不同来赚取不同的钱,随着顾客人数增多,餐厅的工作效率也是逐渐提高,但是每桌顾客的用餐时间都是1小时。

一个新的场景出现了,本来餐厅一个人没有,但是突然之间来了11伙人用餐,前10桌人分别进入餐厅用餐了,剩下这一伙人由于没有餐桌和服务员,只能排队等位,等到那10桌吃完以后才能用餐。前10伙人的用餐时间依然是1个小时,但是最后这一伙人的用餐时间变成了等位1小时+用餐1小时,也就是2小时。

本餐厅的生意非常火爆,突然之间来了35桌人用餐,前10桌人进去用餐,其他25桌人只能外面排号,根据上面的情况我们不难算出,排号1-10的人,他们用餐时间是排号1小时+用餐1小时,也就是2小时。排号11-20的人,他们用餐时间是排号2小时+用餐1小时,也就是3小时,同理排号21-25的人,他们排号的时间就要3个小时,已经超过了忍耐的最长时间,于是他们愤怒的走了。

看到了这里,大家是不是觉得餐厅的排号等位有点像性能测试的场景,我们根据以上的场景提取一些关键性的名词解释吧。

吞吐量:单位时间内处理事务的数量。通常单位时间都按1秒统计,也就是性能测试中经常提起的名词:TPS(每秒处理事务的数量)。通过上面的场景,我们可以计算出该餐厅的最大吞吐量为:10桌/小时。

响应时间:指某个请求或操作从发出到处理,再到接收到反馈所消耗的总时间。通过上面的场景,我们可以认为用餐时间就是响应时间,直接就餐的人响应时间就是1小时,排号1-10的人响应时间就是2小时,以此类推。

平均响应时间:每个请求的响应时间之和除以总请求次数就是平均响应时间。这个指标也是目前大多公司做性能测试中的主流指标之一。

最小响应时间:所有请求中,最小的响应时间。

最大响应时间:所有请求中,最大的响应时间。

90%响应时间(P90) :这个指标在性能测试中经常被大家忽视,不知道这个指标是用来干什么的,甚至不知道这个指标是如何计算的。它的计算规则其实很简单,总请求中按照响应时间从小到大排序,取前90%请求的平均响应时间就是这个指标的值。到现在是不是还不知道有什么作用?

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

mage/format,png)

[外链图片转存中…(img-aw84HraB-1715559987663)]
[外链图片转存中…(img-iNN9N0ts-1715559987663)]
[外链图片转存中…(img-Y6yoLdo3-1715559987664)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值