性能测试知识问题整理
一、性能测试的概念到底是什么?
性能项目分为如下几类:
新系统性能测试类:这样的项目一般都会要求测试出系统的最大容量,不然上线心里没底。
旧系统新版本性能测试类:这样的项目一般都是和旧版本对比,只要性能不下降就可以根据历史数据推算容量,对调优要求一般都不大。
新系统性能测试优化类:这类的系统不仅要测试出最大容量,还要求调优到最好。
二、TPS和响应时间之间是什么关系?
一个系统的吞度量(承压能力)与request对CPU的消耗、外部接口、IO等等紧密关联。单个reqeust 对CPU消耗越高,外部系统接口、IO影响速度越慢,系统吞吐能力越低,反之越高。
系统吞吐量几个重要参数:QPS(TPS)、并发数、响应时间;
QPS(TPS):每秒钟request/事务 数量
并发数: 系统同时处理的request/事务数
响应时间: 一般取平均响应时间
对于三者关系,可以结合这么个场景进行理解:TPS和响应时间在理想状态下都是额定值(联想运行一个压力测试场景来考虑),(以上高速的入口为例,每个入口每秒钟只能进1辆车)把入口看成线程池,如果有20个入口,并发数只有10的时候,TPS就是10,而响应时间始终是1秒,说明并发数不够,需要增加并发数达到TPS的峰值。
理解了上面三个要素的意义之后,就能推算出它们之间的关系(只是关系而已,不是计算公式):
QPS(TPS)= 并发数/平均响应时间
一个系统吞吐量通常由QPS(TPS)、并发数两个因素决定,每套系统这两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换、内存等等其它消耗导致系统性能下降。
另外原文的图比较形象,直接引用过来:
三、怎么理解TPS、QPS、RT、吞吐量这些性能指标?
尽量不用吞吐量这个词(每个人理解这个词的含义都不一样),我们性能测试尽量用具体量化的指标表示吞吐量,比如TPS。
这些指标关系的理解可以结合上面第二条内容,在这里补充一下QPS、TPS、RPS的区别:
QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力;一般习惯用在数据库或单指服务器的评估能力方面,平常只用TPS就够了。
TPS:是TransactionsPerSecond的缩写,也就是事务数/秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数;
RPS:Requests Per Second的缩写,每秒能处理的请求数目,等效于QPS。
理解如下:
1、Tps即每秒处理事务数,包括了:
1)用户请求服务器
2)服务器自己的内部处理
3)服务器返回给用户
例如:这三个过程,每秒能够完成N个这三个过程,Tps也就是N;
2、Qps基本类似于Tps,但是不同的是,对于一个页面的一次访问,形成一个Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。
例如:访问一个页面会请求服务器3次,执行3次select操作,即一次“PV”(页面浏览),产生一个“R”,产生一个“T”,产生3个“Q”
下面列出各项指标的含义:
指标真的太多了,我们最常用的其实就是RT和TPS,一切讲究简单明了,过多的指标和标准只会把人绕晕,增加沟通成本。
四、企业选择性能工具应该考虑哪些方面?以及性能测试工具中是否必须含监控?
1、问题一:
大概会考虑怎么几个方面:
- 学习成本:对人员的水平要求,培训时间成本等;
- 脚本编写:能否录制测试脚本,是否支持GUI操作等;
- 安装部署成本:是否支持一键安装,是否支持docker等;
- 是否免费:开源工具一般都是免费的;但是很多收费工具也的确物有所值;
- 是否支持多协议:比如是否支持 HTTP 协议、RPC 协议等等
- 测试场景:是否有链路、场景编排管理,支持支持将请求编排成业务场景,即常见的一串联场景;
- 流量控制:支持纵向的,上下游链路的请求量逐渐减少,整体呈现一个漏斗模型;也可以是横向的;
- 压力控制:指压测时并发用户数、 TPS 的控制等;
- 数据驱动:大量的测试数据的参数化;
- 分布式支持:支持压力机集群;
- 测试报告:压测结果是否能够图形化展示,提供美观且丰富的测试报告;
- 二次开发的成本:由于时间或人力关系,也需要考虑二次开发成本;
- 性能开销:执行机开销、软件可靠性、执行效率、业务处理能力等。
....
一般工具选择:
比如一般测试接口性能和找系统瓶颈,用jmeter,轻量开源可自定义扩展插件,Jmeter的Report Dashbord插件也能输出完整的报告,或者选用基于Jmeter的压测平台(https://gitee.com/smooth00/stressTestSystem)。如果对业务整体场景流程要求高并且企业预算够(不谈破解版),一般选Loadrunner,毕竟图表好看,界面脚本录制方便,对局方(有时甲方只认可Loadrunner)有说服力。
云测试平台选择(自建还是购买):
首先权衡场景,公司是否业务需求达到这个量级,不为测试而测试。
短期长期思考:短期或没成熟测试团队,可购买服务,长期推荐自建,完成技术栈积累。
顺便提供一下我们常用的一些性能监控产品:
2、问题二:
我觉得一个好的监控系统大概需要包括以下几个方面:
全栈系统监控是前提;
关注于整体应用的 SLA:主要从为用户服务的 API 来监控整个系统;
关联指标聚合:把有关联的系统及其指标聚合展示。主要是三层系统数据:基础层、平台中间件层和应用层。并提供一个全局的系统运行数据大盘,帮助快速找到系统瓶颈。
快速故障定位:快速定位问题需要对整个分布式系统做一个用户请求跟踪的 trace。
只有做到了上述的这些关键点才能是一个好的监控系统,而显然目前的测试工具所带的监控是不能满足的。另外测试工具本身在做监控也有其局限性,如 jmeter 在压测量较大的情况下回传测试结果 Master 节点会容易成为瓶颈。专业的事应该由专业的工具或系统来做(目前无论开源还是商用都会有大量成熟的监控产品),性能测试工具应该专注于压测本身,分出资源来做监控得不偿失(容易监控与测试互相干扰,尤其流量方面)。
五、如何正确理解并发的概念?
问题一:如何理解“服务端的并发能力”这一描述?
首先我们从数据视角来理解,可以把服务端程序用一个模型来看待,即由「网络 API 请求」所驱动的。服务端的领域特征是大规模的用户请求,以及 24 小时不间断的服务。但某种意义上来说更重要的原则是:坚决不能丢失用户的数据,即他认为已经完成的业务状态。服务端必须保证其业务状态的可靠性,这时业务状态才持久化写入到外存。所以对于服务端来说,存储至关重要。它不只是极大地解放了处理效率,也是服务端的性能瓶颈所在。几乎所有服务端程序扛不住压力,往往都是因为存储没有扛住压力。
在衡量服务端的性能,我们还是要服务端视角来看,主要以 TPS 为主来衡量系统的吞吐量,如果有必要用并发用户数来衡量的话,需要一个前提,即响应时间(RT),因为在系统压力不高的情况下,将思考时间(等待时间)加到场景链路中,并发用户数基本还可以增加一倍,因此用并发用户数来衡量系统的性能没太大的意义,也不专业。
对于web项目而言,服务端是整个项目的关键,是咽喉要道,因此也是性能测试的重点。其测试目的当然是要摸清这个要道能同时走多少人(注意这里的人不是在线用户数、并发用户数,而是服务器能处理的事务),因此TPS最能描述服务端的并发能力(TPS、响应时间和并发数的关系可以关注上面所提到的公式)。
问题二:为什么不提倡使用“绝对并发”和“相对并发”的概念呢?
这两个概念对于我们关心的性能并没有太多的帮助,反而让人有点无从使用(概念难懂,加重内部沟通难度,价值不大)。而在线人数,并发数简单明了,很好理解,有利于沟通,是性能测试必备指标之一。
问题三:为什么不推荐用 CPU 来计算并发数?
并发数是业务逻辑层面的,而CPU只是众多软硬件环节中的一环,即使可以借鉴,肯定也是很粗略的估计,在实践中使用价值不大,没有推广使用的必要。
比如单核CPU情况,实际上是只有一个的,在一个特定时刻也只可能有一个程序跑在一个CPU上(因为寄存器只有一组),但是我们在上层观察到的却是系统上好像同时运行着那么多的程序,这实际上是操作系统用进程这个概念对CPU做的抽象。
同时如果你了解「阿姆达尔定律」,就知道多处理器并行加速,总体程序受限于程序所需的串行时间百分比,超过一定的并行度后,就很难进行进一步的速度提升了。并不符合线性关系,也无法估算的。
再说服务端程序性能依赖不仅仅是底层的硬件,其依赖的基础软件还包括:操作系统、编程语言、负载均衡、中间件、数据库或其他形式的存储等。在第一个问题中提到了几乎所有服务端程序扛不住压力,往往都是因为存储没有扛住压力。
最后,还是需要回到第一个问题,即由「网络 API 请求」所驱动的模型上来。
六、为什么线程递增过程不能断?构建分析决策树的关键是什么?
问题一:为什么线程递增过程不能断?
这里涉及经常提到的性能分析方法 ——「趋势分析」,分析性能数据趋势需要对一个时间序列数据的分析,一般采用「线性回归分析」算法。回归分析研究的是多个变量之间的关系。它是一种预测性的建模技术,它研究的是因变量(目标)和自变量(预测器)之间的关系。这种技术通常用于预测分析,时间序列模型以及发现变量之间的因果关系。
假设有 N 个样本点,这里我们可以简单理解线性回归算法就是求一条直线 Y=f(X),使得各点到这个曲线的距离的绝对值之和最小。在这种技术中,因变量(TPS)是连续的,自变量(线程数)可以是连续的也可以是离散的,回归线的性质是线性的。
但在性能测试中,由于系统本身的最大 TPS 上限是固定的,即服务端的处理能力(容量)是固定的,如果自变量(线程数)压力过大,那么系统平均处理时间(响应时间)会被拉长。不过这个时候其实瓶颈早就出现了。
所以在场景压测中的自变量(线程数)递增一定需要是连续的,并且在递增的过程中要有梯度的,且场景中的线程递增一定要和因变量(TPS) 的递增有比例关系,且不是突然达到最上限,这样才能准确找出系统的瓶颈点。如果中间断开,数值就会出现偏差(响应时间会在采样中加入了偏离过大的值,TPS采样也随着偏离,最后造成整体分析偏差)。
问题二:构建分析决策树的关键是什么?
决策树基本上就是把我们以前的分析经验总结出来,在做决策树的时候,一般会经历两个阶段:构造和剪枝。
概念简单来说:
构造的过程就是选择什么属性作为节点的过程构造的过程就是选择什么属性作为节点的过程;
剪枝就是给决策树瘦身,这一步想实现的目标就是,不需要太多的判断,同样可以得到不错的结果。之所以这么做,是为了防止“过拟合”现象的发生。
从性能分析角度来理解:
构造:需要根据经验是对架构的梳理,是对系统的梳理,是对问题的梳理,是对查找证据链过程的梳理,是对分析思路的梳理;
剪枝:需要对不同时间序列性能数据的相关性分析,其核心就是要理解各个性能指标的关系,同时进行证据链查找,根据数据的变化来推断得出各种结论,比如故障判别、根因分析等。
构建分析决策树的关键好比如何画一棵树。先确定主干(主要流程),然后添枝干(组成部分),最后画树叶(定位问题)。从上到下,从左到右,拆分......
从性能瓶颈判断分析的角度入手,是性能从业人员该有的逻辑。每次我们分析一个性能问题时,逻辑总是这样的:
七、代理录制的逻辑是什么?当访问网页时,为什么第一个请求至关重要?
问题一:代理录制的逻辑是什么?
你也许听过这样一句至理名言:“计算机科学领域里的任何问题,都可以通过引入一个中间层来解决”。TCP/IP 协议栈是这样,而代理也是这样。
所谓的代理(Proxy)是 HTTP 协议中请求方和应答方中间的一个环节。既可以转发客户端的请求,也可以转发服务器的应答。不管是在本地代理还是远程代理,都是通过代理的设置,在客户端和服务端之间插入一个中间件,中间件接手客户端的请求并转发到服务端,说白了就是端口映射(Port mapping,端口映射工作在传输层,重定向工作在应用层)。
代理常见种类:匿名代理、透明代理、正向代理、反向代理。
代理可以做的事:负载均衡、内容缓存、安全防护、数据处理。
此处简单理解 JMeter 录制脚本则通过代理是通过转发数据包并拦截上下行的数据解析生成脚本,但录制出来的脚本都是原始的 http 请求,并没有经过适当的封装,所以录制功能比较简单普遍,Loadrunner也有代理录制。
在性能测试的过程中,有很多新手对录制的逻辑并不清楚。代理录制的这个动作他们也可以很快学会。但是很快就忘记了,我曾经给一些人手把手教过如何做代理录制。结果第二天就不记得了。其实并不是不记得动作,而是出了问题,脑子里没有判断问题的逻辑,所以根本无从下手排查。
另外,你需要注意的是,录制功能并不是性能测试工具必备的功能。对性能测试工具来说,关键功能是能实现模拟批量的真实请求逻辑。至于脚本是如何实现的,怎么做都是可以的。所以我们可以用其他的工具,比如说BadBoby、Fiddler、Wireshark 抓到交互请求,再放到 JMeter 或Loadrunner中实现脚本,也完全是可以的。
当然没有脚本就无从实现压力,所以脚本的实现是性能测试工程师必备的基础技术,理解原理也是必须的。
问题二:当访问网页时,为什么第一个请求至关重要?
实际上,对浏览器来说,他们做的事情,就是把一个URL变成一个屏幕上显示的网页。这个过程是这样的:
1.浏览器首先使用 HTTP 协议或者 HTTPS 协议,向服务端请求页面;
2.把请求回来的HTML代码经过解析,构建成 DOM 树;
3.计算 DOM 树上的 CSS 属性;
4.最后根据 CSS 属性对元素逐个进行渲染,得到内存中的位图;
5.一个可选的步骤是对位图进行合成,这会极大地增加后续绘制的速度;
6.合成之后,再绘制到界面上。
简单理解浏览器的工作原理就很容易回答这个问题了,第一次请求需要构建 Dom 树(内存中的数据结构),而这棵 DOM 树其实就是前端程序的业务状态。没有第一个请求创建的DOM树,后面的请求就没有地方放了。
八、HTTP的GET和POST请求,在后端处理中有什么不同?断言的作用及如何使用断言?
问题一:HTTP的GET和POST请求,在后端处理中有什么不同?
get请求一般是向服务器索要数据(理论上是,关键看get执行的业务操作是什么),post请求是向服务器传送数据的,浏览器限制了get的传送量(HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制,IE对URL长度的限制是2083字节),post可以大量的把数据传给服务器(理论上讲,POST是没有大小限制的,起限制作用的是服务器的处理程序的处理能力【Tomcat默认2M】),一般情况下get请求,请求体是空的,请求只发一次 ,如果是post请求,数据会放入请求体中,并且会根据请求头里content-length的长度分两次或多次传给服务器,直到与content-length的长度相等时断开传送,get和post请求服务器数据可以说都是不安全的,传送和接收都是明文以字符串形式交互数据的,想要安全,请求之前需要加密处理。
GET请求对于springboot框架来说是通过 @RequestMapping(method = RequestMethod.GET)中的@GetMapping来处理,这是框架定义好的接口,关键也是看get执行的业务操作是什么;
POST请求对于springboot框架来说是通过 @RequestMapping(method = PostMapping.GET)中的@PostMapping处理数据;
一般对数据请求频繁,数据不敏感且数据量在普通浏览器最小限定的2k范围内,这样的情况使用GET,其他情况使用POST
问题二:断言的作用是什么?如何使用断言?
断言用的是幂等性原理:
什么是幂等性:
一次和多次请求某一个资源应该具有同样的副作用(对资源变更带来连锁反应或影响):f(x) = f(f(x))。
为什么要幂等性设计?
系统解耦后,系统间服务调用存在三种状态(前两种是明确的):
- 成功
- 失败
- 超时(中间状态)
怎么做幂等性设计?
- 下游(响应方)提供查询接口,上游(请求方)对于状态疑异订单进行查询
- 下游(响应方)系统幂等性设计:确保不会重复
- 全局ID:Twitter 的 Snowflake 算法/UUID
- 存储冲突来解决(唯一约束)
- 插入重复无效,
insert into … values … on DUPLICATE KEY UPDATE …
- 更新状态:
update table set status = “paid” where id = xxx and status = “unpaid”;
HTTP幂等性
- HTTP GET 方法用于获取资源,不应有副作用,所以是幂等的。
- HTTP POST 方法用于创建资源,所对应的 URI 并非创建的资源本身,而是去执行创建动作的操作者,有副作用,不满足幂等性。
- 只有 POST 需要特殊处理,其他都具有幂等性
- 前端生成 token,后端存(唯一约束)
- PRG 模式
断言(又称检查点)是为了校验请求的返回值是否符合期望的结果(涉及到业务逻辑的断言需要对响应内容进行检查,包括关键字检查、或者数据处理逻辑结果检查等),只有增加合理的断言,才可以做性能测试,如果不加断言就不知道业务请求是否正确,再加没有断言TPS会很平稳,对实际压测结果意义不大。
九、关联和断言的逻辑是什么?它们取数据的特点又是什么?
关联:有关有联,该数据一定是根据前面的业务获取的,是一个变化动态的,从服务器获得的,否则就可以在脚本中直接写好,变成一个参数了;同时该数据也一定是后面业务得以进行的必须输入,否则就没有存在的意义了;因此,关联数据起了一个承上启下的作用。取数据特点,从服务器返回信息中取数据,这个数据是动态的,且是后续业务必须的输入数据,需要继续使用的。假设一个业务场景由多个请求构成,那么关联可以理解为前一个请求的输出作为后一个请求的输入。并且可以将关联的值参数化,例如Token,jobId等;关联示意效果图如下:
断言:断言的逻辑可参考上一问题中的幂等性。一个请求从执行开始到结束之中,所经历每个步骤都可以“暂停”,那么暂停的这个动作即为断言。通过断言你可以知道代码的运行逻辑,对应的输出是否合理,Debug的好帮手。断言美其名曰一言断分晓,明查是对是错矣。提取服务器返回的可判断业务成功的数据,对其进行判断,从而获知业务是否成功。取数据特点,也是从服务器返回信息中取数据,在业务成功时该数据是一样的,主要用于判断,判断结束后一般不会继续使用。
十、为什么参数化数据要符合生产环境的数据分布?要关注组合逻辑关系?
问题一:为什么参数化数据要符合生产环境的数据分布?
性能模型中的业务模型是真实场景的抽象,即需要的数据通常都是从生产环境中的数据中统计来的,其关键就是「数据必须保证仿真」。那么性能测试的时候我们需要特别注意压测流量以及相关的数据,必须保证它们的多样化和代表性,否则会导致测试结果会严重失真。压测本身就是服务于生产环境,所以参数化也要依赖业务逻辑,故在参数化之前,需要分析真实业务逻辑中如何使用数据,再在工具中选择相对应的组合参数的方式去实现。比如,当使用相同的测试数据进行重复测试时,如果压测请求不够大,那么各种缓存可能会严重影响测试结果。
参数化的数据分布要考虑顺序、随机、唯一等分布方式,作用:
1、减少数据命中率;
2、减少缓存命中率;
3、符合性能压测价值,测试结果更真实;
问题二:为什么参数化数据要关注组合逻辑关系,而不是随意设置组合?
因为参数化数据的逻辑组合关系会直接影响参数化数据的分布情况,即数据是否均匀?数据是否稳定?是否保证测试时间足够长?是否满足测试的负载请求足够多和数据足够多样化?是否最大限度地减少或者掩盖缓存或者保证参数化设置的有效性?另外也从侧面反映压测人员的技术专业性。
参数化要规划好各个参数之间的组合逻辑,比如用户名和密码的一一对应关系(对不上肯定不行),参数之间的顺序,另外不同参数之间还有其他逻辑对应关系,比如一对多,多对一,互斥关系等等。业务规则决定了参数文件不能随便组合;如果随意组合参数,会影响事务成功率或与实际场景不符;
在Loadrunner中有相关的参数化组合配置方式:
对于Jmeter也有参数组合配置:
Recycle on EOF? :这里有三个选择,False、True 和 Edit。
Stop thread on EOF?:这里有三个选择,False、True 和 Edit。含义和上面一致。
Sharing mode : 这里有四个选择,All threads、Current thread group、Current thread、Edit。
Jmeter还可以结合Random随机函数,或是自定义Java函数或是Bealshell脚本实现各种灵活的参数组合配置。