00:00
Hello,大家好,然后之前是分享了一些接口测试和自动化的相关内容,然后接下来我们开始分享性能测试的,然后大家可以扫描这个二维码,关注公众号,后台回复getate也能看到那个项目的开源地址,然后我们现在开始讲这个性能测试啊,这个性能测试的框架呢,分两类啊,一类就属于这些啊CD base这些这个虚拟类和其他继承于这个虚拟类的其他类,它主要的实现的功能就是呃创建呃任务,创建多线程的任务,然后会有一个啊执行的类,这个多线程执行的类,然后我们今天就呃先讲一下这个基础这个类啊,然后大家看一下这里用到了一个呃泛型啊,这个泛型到啊之前之所以考虑。
01:00
把这个范型加到这个里面的话,呃主要是呃考虑到一些匿名类,实现匿名类的时候发型会比较方便一点,但是后来发现呃其实自己的想法是错误的啊,这个发型类的话,在后来实际应用中啊,其实用的并不多啊,可以就是不嗯,而且匿名类这个呃也用的不是很,就是很多时候匿名类不好处理,呃所以说现在呃在实际工作中,基本就是自己去先去先去实现这个多线程类,然后再去呃创建多线程任务,去执行多线程,然后呃这个呃所以说但是这个代码又一直没改,嗯所以说大家可以把这个发型给忽略掉,然后呃首先看这个s mark,这个是标记,嗯这个标记呢,就是我对于每一个线程的任务的每一次循环,因为一个线程任务就是。
02:00
绑定了一个线程,它其实是内部里面是有很多循环的,然后这个是标记每一次循环的一个string字符串的标记啊,这个主要用于什么呢?啊,主要用于标记每一次,每一个线程的每一次,呃循环一般来说就是HTTP请求,或者说是一组HTTP请求来标记它,标记它是为了记录呃这一这一组或者是这一次的呃循环的耗时,然后用来做那个日志追踪,或者说呃一些错误排查用的啊这个错误number,嗯,还有一个,呃,应该还有一个file number,呃,我看一眼啊啊。这个错误number的话,呃就是失败的次数,然后这个q number是执行的次数,然后这个cutdown拉奇,这个是一个呃呃法,呃为了使多线,因为我不创建了很多线程,为了是这么多线程,呃有一个同步的呃结束的一个标记,然后这个就这个类就可以呃创建呃那个一个这个对象,然后去绑定这一组线程,然后完了之后就可以使呃实现一个使等待所有线程结束的这么一个功能啊这个类呢,在那个呃性能测试中,呃有那个服务端的呃异步查询转同步,这个会用到的会比较多一点啊具体的使用方法的话,呃那个那篇文章写的是比较清楚,也比较简单,这个大。
03:44
待会儿给大家啊,应该今天有时间的话,会给大家看到那个current这个呃类里面去怎么去使用这个对象的啊,然后大家看这个标记对象啊,这个这个标记对象呢,大家看一下这个接口,其实就没什么东西,就是一个标记方法,还有一个可能因为在性能测试的时候,就很涉及到很多的考对象拷贝,所以说啊,每一个都需要呃实现这个可能接口,然后。
04:15
呃,实现这个方法,然后这个mark呢,就是呃,Mark每一个线程,对每一个线程任务,然后每一次循环,或者每一个线程,这样的话可以去标记到每一个线程,或者每一个线程的某一次巡摸,每一次循环这样的,嗯,这个功能跟这个。跟前面这个cine mark这个有点类似,嗯,部分功能是重合的,但是这个是标记的是一个,呃,大家看这是一个标记的方法,方法是这是一个标记出来的string字符串,但是它这里面这个方法反馈回来的还是一个string,它主要就实现一个标记的功能,其实呃用处的话就是在于呃在排查多线程任务,多线程压测的过程中,一些超时情况,还有一些错误情况,比如说像我们现在就会有一个request ID,我们去排查每一个请求,它具体耗时在哪这样的,然后这是一个构造方法,然后这个这个T呢。
05:24
嗯嗯,这个是访问那个那个我们之前设置的这个发型这个类的,呃,这个车行对应它这个属性,它的访问它的,但是我发现Java跟那个呃格位有点不太一样,所以呃写了一下这个方法啊,这也是,但是这个方法也基本上就是很少去用啊这样的,因为Java的话,如果你把这个T传进去,比如说是string嘛,它就可以直接调string的很多方法,直接get get,然后返回回来就是一个string对象,但是如果是格位的话,就get的话,就返回回来的,就可不是不是那个格位对象,反正就是一个,呃,就是咱们在平时获取到的对象类型的,就哈希一个对象的类,然后加哈希子艾哈西值这种好像是这种这种形式的,所以说当时呃写了一个这么一个方法,返回回来是一个啊t two string的这样形式,这个大家。
06:24
忽略掉,因为这个用的实在是呃很少,因为我们现在都改改用那个直接去先实现类,然后再去用多线程类去创建多线程任务,然后后面这些就比较简单了,就是比before,就是再进行多线程循环,呃不再进行单个线程的多次循环之前所进行的呃操作,这个是呃循环中的操作,然后大家看这个注释,一般就是压测的时候重试控制器,不再重试,只要我的采用的方案就直接把那个return time改成零就可以了,然后这个after,大家看这个after,就是在这个多线程类的所有循环结束之后运行的方法,就是这个抗单上去,然后看上就减一,运行完了就减一,是这样的,然后设置这个就set的这个,这个这个大家应该比较。
07:24
能看到,然后这是对象拷贝的,然后嗯他在这个的里面我做了一个操作,就是用了深拷贝这个功能啊,所以这个这里面会有一个注注注释,就是说必须要实现这个接口啊,但是呃一般来说呃会直接重写可能方法会比较合适,因为呃很多时候我们的呃有些对象它是不支持深拷贝的啊,有有可能会会比较麻烦,有可能我每一个呃任务,呃对象的任务都会涉及很多对象,拷贝起来会比较麻烦啊,所以说是呃后面需要去继承这个类的,呃继承实现这个类其他功能的那个类需要重写这个合用方法,那如果他不重写的话就会掉啊升卡位的一个方法,呃然后这个是呃状态的,呃这个状态就是嗯第一呢,就是呃为了。
08:24
就是标记一个当前线程的那个失败,这不运行状态,呃就是啊,比如说我线程预计,呃比如嗯请求100次,但是他错次数太多了,比如说我我现在设置的只有十次,如果他请求失败,或者说呃呃一一组请求,呃像某些业务验证失败的话,呃就是请求,就算是一个循环就执行失败,呃失败次数超过十的话,就认为这个线程的啊已经是执行失败了,就没必要继续再执行下去了,因为一般在那个压测过程中啊,我们都要保证业务是100%那个成功的。
09:08
但是啊,有些时候我们需要统计一下那个错误率,有些是呃可能就是呃有极少量的他业务验证失败,或者说是处理请求不过来,返回了一个啊404啊,或者返回一个500这种呃结果的话,我们需要统计一下这样的,所以说是啊有一个start sta那个这个方法,然回的是一个不尔值啊就是啊们是关闭的,然后我们找做,然后后面有实现这个类的,其他类的话是需要写一下这个方法的,到时候我给大家演示一下后面两个实现这个类的两种压测模式,嗯这格位的乘法调用的话,这个这个嗯就是格位,它有一个特性,就可以重写,呃重写那个操作符,呃乘法对应的这个呃是谬啊,这个方法名就这个,然后呃大家看这个range。
10:08
Number,然后比如说就是当前有一个对象乘以十,然后就是让你十,然后map object,然后就是调当前这个对象的可方法,然后再收集成,呃,收集到一个list里面啊,是这样的,大家看这个range其实就是一个啊,这个int是Java啊,将个JAVA8以后的一个写法啊,大家可以用分循环也可以代替的,这就是一个,呃,简单来说就是把这个对象copy多少份,然后再把这个这些嗯,Copy出来的对象放到一个list子的里面啊,就这么简单啊,我看有没有用到的啊哦,这个地方不不支持那个idea不支持它这种应该是可以用到的,就是说嗯,我看这个就直接拿一个新建好一个对象,然后直接乘以这个,因这pass就可以了,直接乘以个十。
11:08
回来就是一个呃十个长度的那个历史的这个对象,然后我们就可以针对性的这些这一组对象去做一些呃相应的创造创建多建任务这样的操作,然后这个就介绍这么多啊,然后嗯,在这里面大家需要着重的看呃了解一下就这这个吧,看大这个是用的会比较,在那个多线程编程里面会用的会比较多,不管是我觉得测试用的也会比较多,因为它是一个比较呃好的那个去呃等待任务多线,呃不是多线程任务结束的啊,执行结束的这么一个,呃工具类吧,其实也也比较简单,大家还有一个就是它是现安全的,现现不安全的肯定也执行不了,然后我们看这个,嗯,Conrrence这个这个是。
12:08
啊,主要是用来执行压测的,然后咱先看一下它的一些属性,就开始时间啊,结束时间啊,对当前任务压测的一个任务描述。然后任务集,就这个历史的这个,嗯,然后这个是线程数。啊,总的失败次数。呃,执行啊,这个失败的总数,这个执行失败总数其实就是一个失败的总数,还有失败任务的数,因为我们比如说我创建了100个线程,相当于有100个多线程任务,这些多线程任务每一个这抢求失败超过十次,我就认为它是这个线,线程任务就失败了,就这个一个这个错误的一个是嗯执行任务的失败总数,还有执行总数,然后嗯,记录请求时间,呃这个请求时间呢,我是用的是那个呃long类型的,然后两个时间桌相减long类型的,然后这个呃这个是一个呃多线程,呃线程安全的。
13:18
List他继承的应该也是一个发它是一个啊class你看它是这个,然后他实现了这个list史的方法。然后嗯,这是快车的信息,也是一个线程安全的历史的,然后这个呃就是呃用来标记什么呢?比如说我在测试过程中,哦,标记超过呃两秒的所有的请求的啊,Request ID,然后把它的request ID和请求时间记录下来,或者说记录一些别的信息,然后存下来之后,呃如果压测不通过的话,我把这些呃信息发送给那个开发,让他们去排查,或者说是跟开发一起去排查这些问题,嗯,大家看这个,嗯这个就是呃,Filter service这个嗯这个待会给大家讲一下吧,这就是执行那个线程,执行那个多远式任务的线程池啊,他这还有个计数器啊,我教他计数器啊,具体的可能有别的仓储。
14:29
这个是它的构造方法,你看这是一个,如果是一个线程的一个线程任务的话,呃,还有一个呃,线程执行的线程数,然后这个就是我们看一下这个新number,这number就是你看a service等于AQ等于new five,呃,New fix,这个是一个定的程啊,这个也是一个,呃,就始化这个数器,大家看都是那个根据那个设定的线程值的,嗯,线程数确定的,然后这个是大家看一下,哎,这个系的就是他的线程任务集。
15:14
任务集里面去放这个当前这个对象的拷贝对象,然后这个线如果是嗯,用这个线程线程这个任务那个list来去构建这个呃对象的话,就是呃,它的线程数就是这个list的S长度,然后它的list啊不,它的这个任务数就等于呃当前传进来这个list子的,然后还有一些就是下面这些,呃就比较比较就是在之前呃就前面两种创建那个呃执行对象的话,呃的两种形式,呃多加了一个描述,就任务描述都都一样的任务描述,然后这会有一个任务描述加了一个时间,当前时间。
16:10
这是它这个是有的构造方法,就是通过一个线程数,然后去把那个a service和那个cut去啊做一个初始化啊这样啊,这个是没有空参的,就是private,就是不不不需要别的去调用这个空参的,然后构建完之后,我们去需要去执行这个呃,Start start就是执行啊执行的话就是我们先初始化这个呃,Start time,然后然后就这个分行完,这个比较简单啊,大家看一下就行了,就是S,我们把那个那个呃任务list的呃,包含所有的线多线程任务的一个list里面的多线程任务的对象全都拿出来,然后set一下。
17:05
把这个当前这个con current这个对象的这个呃,Count down countdown lunch到这个对象,给它设置成啊任务多线成任务的这个对象啊,这个有什么好处呢?就是在设置进去之后,然后每一个任务结束之后就会调一下这个对象的啊cutdown这个方法,然后就相当于啊,其实里面就是减一,然后减到零了之后就表示所有的线程都已经执行完了,然后我们再用这a q service去执行当前这个C的啊大家大家可以看一下这个,然后呢,然后我们再去效把这个执行线程池啊这些还有这个康到览气,然后等它关闭,然后我们看它怎么关的,就是在看当氮气wait就是一直等待。
18:00
一直等待所有的呃,线程结束完,就是比如说我创建了一个,大家看一下这个创建的方法里面有一个啊,你这个它的线程数嘛,每个线程结束,呃,每个线程大家看啊,每个线程after。After里面都会有一个cutdown这个方法,Cutdown之后来看,Cutdown之后它就release释放一个,就把它一了,就相当于呃,它那个数减一减到零的时候就就表示诶,我我这个东西已经执行结束了,然后这所有等所有的线程执行结束之后,然后我们会记录一个结束时间,然后这个地方呢,就是大家看这个地方就是我去计算,我去把这些所有的线成的它的执行状态全,或者说它的一些执行的数据全都拿出来,然后做一下那个简单的呃统计啊,这是你看他如果只要有一个线程执行任务失败的,哎,我们就认为他报加价啊,就是失败的任务线程加一,然后嗯,错误的数等于每个错误不,每个任务多线程任务错误数的累计,然后执行总数等于每个线程数。
19:17
啊,每个呃,任务数执行数的累计,但是有时候嗯嗯,这个累计这个数跟我们设置的,因为我们可以设置一个固定次数的一个呃执行,但有时候这个执行数跟我们那个次置那个数不一样,有的时候就执行失败的话,就不会执行数就不会加一啊这个知识点到时候呃,下一期我们讲下面这两个两种压测模式的时候再讲,然后下去打个日志,多少个线程,执行多少次,执行多少秒,然后总的错误的,然后这一个,然后over over是这个,它会返回一个performance,呃,这个绕B啊,大家看一下这个B里面就是描述结束时间,开始时间,然后这个是table table应该没什么鬼用了,然后这个是线程数啊。
20:17
Q,然后T平行响应时间QPS,然后这些啊total这个啊总水牛次,然后我看这个偷是什么鬼,可能我写错了吧,推哦,这个推后可能是嗯,我看一眼啊推哇,看着有点怪退步第几个参数啊,最后一个参数哦,这个这个想起来这是一个图形化输出测试结果的一个那个那个呃,一个时均字符串这个回头再。
21:17
呃,之前给大家分享过一篇文章,就是把那个测试结果,呃分享的那个呃转化出来啊。我看看有没有。具体的结果。呃,应该是没有的。就是展呃,展示成一个图形,就用string转换成一个图形,然后这个里面。嗯,是执行了这个操作会,呃找一下啊。我还是这样走吧。它主要利用了这这这这几个特殊的符号,就是这是1/8,这是2/8,这是呃7/68,呃8/8这样的一个符号去展示一个图形啊是这样的,然后嗯,这个O这个地方就会展示这个,然后大家看一下,计算完之后会在数据库里面会存下来。
22:31
啊,是这样的。我给大家看一下那个,我找一下我们写的项目里面的压测的结果好像有点大。
23:16
我搜一下。哦,找的时候还找不着了。啊,在下面这个地方啊,就这种通过这种形式,然后把那个测试数据给展示出来,纯类型的测试数据。啊是这样的,就是其实呃就是嗯,之前是调用那个Python的一个库,可视化库去做的,可能比较麻烦,然后就自己做了一个简单的,大家看这个啊高又低,然后这是八分之几,然后这是一个八分之几,然后这是这应该是1/8的,然后这样一个大概的响应的一个曲线,啊这里面就是做了这些工作,然后这个over呢,然后就是做了这些,先是先把那个测总的测试结果存一下,完了之后存完之后呢,呃,我们看这个啊,再来看这个是那个呃线同步的去把这个。
24:35
那个结果存,如果是空的话,然后就return,如果不是空的话,就把这个存下来,这个原因是因为呃呃是所有的线程都会去调用这个呃方法去存,然后如果是每个线程都不一样的话,还有可能会导致一些问题,就比如说我第一个线,比如说我有两个线程,第一个线程存了一次,第二个线程又存了一次,因为大家看呃。
25:09
大家看这个C这里面就是把它当做一个list string,然后存存出来的,所以说呃,因为有可能是你看大家看这个question mark,这是一个静态。为什么用静态的呢?因为呃在创建现成任务的时候,可能呃这个current还没有创建,所以说要用一个静态的那个呃参数来去存这些东西,存完之后嗯是需要将这个a time和这个呃request mark这个给清空掉,因为不因为要呃防止下一次有别的任务进来,然后这里面呢,应该是需要一个啊全局的一个K来保证,同时只有一个压测任务在进行,是这样的,但是我们都是本地执行的,本地执行的呃,压测的现在是本地执行的,而且这都是单机执行的,没有说放在服务器上。呃做一个性能服务跟这个就代码有点不太一样,如果是做一个性能测试服务的话,它会有一个全局的K来控制一个当前,呃,只有一个呃。
26:28
多线程任务在跑,然后下面这个是啊,计算这些性能指标的就这些啊,主要是那个平均响应时间,QPS错误率,还有那个嗯,失败率啊这一些的啊OK,这个是这下面这些就是做计算用的,因为我是先存,然后再算,就防止呃,我下次可以追踪的时候就可以继续的去,呃,大家看一下这个浪里面,好,这就是这样的,呃,记录的每一次请求的时间啊,这个就是记录的是呃标记前面是标记,后面是响应时间,那后面的也是这前面的标记后面的是响应时间啊不对不对,前面的是时间,后面的标记啊说错了,这就是响应时间,后面是它的标记啊,我们都用的是那个。
27:28
快速ID块,我的request ID是一个开头的,加两位水,这样应该加三位,随机数完了之后,后面是每个线程递增的,这样也就保证那个基本能保证那个它是不重复的啊,是这样的啊,今天的视频就先到这儿了,讲的有些冲忙,你主要因为那个微信它只能传30分钟的啊,下期再讲一讲那个后面两类,呃,两种多线程模式吧,一种是定时的,一种是定量的啊这样的好啊,欢迎大家关注我的公众号拔一拔。
我来说两句