在写这篇之前本来是想写一下关于“设计模式”的内容,但仔细想了一下其实在测试开发的面试中很少有问到设计模式的,如果问到了也只是一些简单的关于单例设计模式、工厂模式等比较简单一些模式,大家可以自行在CSDN中搜索常见的一些简单面试题目即可。
我这里推荐一本之前看过的书籍《大话设计模式》,里面介绍了23种设计模式,有时间又感兴趣的话大家可以看看。关于设计模式如果要的简单总结的话,那就是要活用java中类继承、接口设计和动态代理以及反射。要基于功能现在和未来的一些特性去进行设计,满足程序的低耦合、高内聚和可扩展。
前言
“实践是最好的老师”这句话真的什么时候都不过时。之前一直看了很多性能测试的内容,但是苦于没有一个真正的可以练手的项目实践一下,所以虽然看了但是始终在脑海里没有一个直观的印象。最近国庆节来临,为了应对可能增长的流量高峰,我们部门的基础服务进行了一轮全链路的性能摸底,虽然没有做过,但我明白这是一次很好的学习机会,所以也积极参与了其中。之前一直觉得的很难的东西,实践了之后你就会觉得原来也不是想象中那么难。年轻的时候还是要多广泛地实践和体验。
学习资料推荐
如往常一样,我会先列举出来我所用到的学习资料。本篇内容也是对其中的内容消化之后整理的总结。
性能测试思路
在做一件事情之前,我喜欢先理清楚思路之后再去行动。这应该也是为什么之前学习性能测试的过程中觉得非常难的原因,因为之前很长一段时间里都陷入了如何去掌握诸如loadrunner、jmeter等此类工具的误区之中,而这些工具上又有很多复杂的按钮,所以顿时更加让人头大了。
其实在我看来性能测试和一般的手动测试具有相同的逻辑,只不过在性能测试中相应的步骤所需要用到的技术和工具可能会更加复杂。例如,在一般的手工测试中包含了:(1)测试目标设定;(2)测试场景分析、测试用例和预期结果设定;(3)测试环境和测试数据准备;(4)测试执行;(5)测试结果观察,发现问题;(6)问题分析和定位问题,解决问题;(7)复现测试过程来验证问题是否得到解决。在一般的手工测试中这七个部分的操作都非常简单,然后在性能测试的过程中对应部分所需要的操作以及使用的工具可能就非常复杂了,这也是做性能测试的门槛所在。
在性能测试中以上七个部分每个部分都需要我们去进行学习,如果你能回答上面的几个部分并有了相应的实践那我觉得算的上是有一定的性能测试经验了。这也是我为什么会推荐段念的《软件性能测试》这本书的原因,他能够帮助我们解决前面4个部分的内容,同时高楼老师的极客时间的专栏又可以作为一个很好的补充。
性能测试的目标
在开始一次测试之前,我们应该先想一下我们的测试目标是什么。在一般的业务测试过程中,我们的目标往往都比较简单,是为了验证产品功能是否符合产品需求。那么在服务端性能测试的过程中我们的目标是什么呢?我很赞同段念在他的书里面所写的服务端性能的三个视角:
- 从用户的角度来看,我希望我每一次操作所使用的响应时间越短越好
- 从系统管理员的角度来看,我不仅关注响应时间,我还希望知道我的系统在不影响响应时间前提下能同时支持的并发访问用户是多少、系统有多大的吞吐量。
- 从开发的角度来看,我就比较关心我写的程序有没有bug。希望能够知道系统架构是否合理?数据库设计是否存在问题?代码是否存在性能方面的问题?系统中是否存在不合理的内存使用方式?系统中是否存在不合理的线程同步方式?系统中是否存在不合理的资源竞争?
所以从我的角度总结来看我们可以将性能测试的目的分为两类:(1)找出系统中存在的缺陷(2)在一定的性能指标下(可承载的并发用户数目&平均请求响应时间)评估当前的服务器资源是否合理以及系统的瓶颈所在,或者是说为了到达一定的并发和响应时间的要求我们应该如何规划我们的系统中的各个资源。
性能测试的术语
性能测试的实施过程中需要多方的参与,为了让开发或者同组的QA能够看明白整个测试方案以及测试报告,我们需要对齐我们所使用的一些术语,这一点在高楼的专栏中也有提到。在性能测试的过程中切记我们根本无法做到精准的并发,我们只能说在一段时间内平均的TPS或者QPS,在真实的世界往往也是这样的。
在性能测试过程中我们常用的几个术语如下:
(1)响应时间:这个时间通常包含了很多:网络传输时间+应用服务&数据库的延迟时间+前端页面解析时间。我们通常在进行服务端性能测试的时候,更加关注的是应用服务&数据库的延迟时间,从而能够帮助我们定位出相应的问题。
(2)并发用户数:在进行性能测试设计的时候,要通过一定手段来得到我们需要模拟的并发用户数目。如何合理的估计并发用户数有很多方法,我们需要进行合理的选择。但是往往我们并不是非常精确的关心这个指标,通常会用实压机上启动的线程数目来代替。
(3)吞吐量:吞吐量可以使是:请求数/秒,页面数/秒,字节数/秒。而我们通常要么使用QPS(每秒的请求数)或者使用TPS(每秒完成的完整事务个数)来表示。
(4)性能计数器:在性能测试过程中,我们需要监控受压系统的性能指标。要在清楚了解系统架构的前提下,去监控系统中重要环节的性能指标。如主机的OS指标、应用程序的JVM指标、数据库服务器的OS监控、MYSQL的指标监控,在一些复杂一点的系统中还会涉及redis、MQ等基础组件性能的监控。
(5)思考时间:用户在进行操作时,每个请求之间的间隔时间。加入这个时间往往是为了更加真实的模拟用户操作,如果仅仅是为了测试峰值请求,可以不加入思考时间。
性能测试计划编写
我们在做任何测试之前都应有提前拟定一个计划,这样才能够做到对测试进度有所把控,按时完成任务,交付测试结果。尤其在性能测试中我们更应该事先就拟定好测试计划并找相关的人员进行review,确保测试过程的正确性。我必须诚实的说的,我目前并没有很多正式的性能测试经验,目前所写的内容是对前面所提到的两份参考学习资料的消化理解和总结,处于对知识产出者的尊重,希望在工作中有实际需要的同学可以购买相关原版的资料进行学习。正如高楼老师在其专栏第一篇所说,一个性能测试计划中应该包含以下几个方面:
(1)和一般的测试一样,首先我们应该先明确的是我们的性能测试所涉及的业务场景(其实在我的理解中无论是基本场景还是容量场景,都是我们预期要测试的业务场景),并对待测系统的架构进行梳理;明确在特定的测试环境下,在这些场景中我们预期测试目标;
(2)在对系统架构进行梳理之后,我们应该要进一步明确在测试过程中我们需要监控的各个模块的性能指标(我们在后面进一步细述);
(3)然后我们需要有计划去准备我们需要的测试脚本,这其中也包括了压力测试数据、铺底测试数据的准备等(这个过程需要我们有耐心);
(4)接下来就是在特定的测试环境中,执行我们的测试结果,并观察我们所监控的各个性能指标,去分析系统瓶颈以及问题所在。
以上4个步骤,每一个都需要有相应的思考能力和技术实现能力,这也是为什么性能测试看上去是那么的神秘和困难。做好性能测试不是一朝一夕的事情,需要多找机会去实践。
性能指标简述
关于性能测试过程中需要监控的指标,我这里就写一些目前我理解并有所感受的指标,其他更多的指标后续有实践之后再补充上来。性能指标主要分为两类:
(1)客户端的性能指标,主要有三个:响应时间、吞吐量和错误率。一次成功的性能测试,其压力应该是解题递增的,并且如果系统良好,其响应时间和吞吐量也应该满足阶梯递增的归类。如果我们从曲线上无法看出明显的规律趋势,那么很有可能我们的压测脚本、压测数据,或者系统配置上有问题,需要进一步的定位和排查。为了能发现有效的问题,我们至少应该保证压测脚本的有效性。
(2)另一类是服务端的性能指标。要观察什么指标应该基于你对整体系统架构的理解去逐步拆解和细化。但是在高楼老师的专栏中给出了一个指标监控的通用原则“先全局监控,再定向监控”,我们应该先通过全局的监控指标来发现瓶颈和问题,然后为了追综瓶颈和问题发生的原因,我们应该去看定向监控的指标来进一步定位问题。全局监控的指标主要是OS性能计数,定向监控指标就有很多了,但是这里我主要学习了JVM性能计数器以及与MySQL相关的计数器。
OS性能计数器
所谓的OS我想大家应该都知道,就是机器上的操作系统。要知道主机上应用程序之所以可以运行就是因为有操作系统的存在,它帮助我们执行了应用程序中命令。因此在程序运行的过程中,监控OS相关的指标就是自然而然的事情。高楼老师把OS里面要要监控的指标总结为了下图所示,其中红色标注的是常用的指标。出于对知识的尊重,我这里就不把这些单独指标的含义在本专栏里面列举了,大家工作中有需要的话可以自行搜索或者查阅高楼老师的极客时间专栏。
刚看到这个图是不是要疯魔了,有这么多指标要看,还要一个个理解其中的含义,的确是需要花费一些功夫的。但是如果从大类上来看,OS的性能监控指标主要包含了6大类:CPU、内存、IO、网络、System、Swap。如果大家熟悉计算机