说在前面
提到性能测试,大家想到的就是使用工具对应用进行加压,看看应用能承受多少并发,TPS(Transactions Per Second)是多少,交易响应时间是否在接收的范围内。不错,这些都是大家最关心的应用的性能指标,也是每个性能测试项目输出的结果。然而,要实现这样的效果却并不是一件简单的事情,因为性能测试是一个十分复杂的系统工程,对测试人员的能力水平提出了更高的要求,需要性能测试人员具备非常全面的知识与技能,能够定位应用的性能瓶颈,并提出适当的优化方案。
通常,要对一个应用进行性能测试需要经历需求调研、环境准备、脚本开发、数据预埋、场景设计、场景执行、应用监控分析、瓶颈定位、瓶颈修复、回归测试、结果整理、输出报告等多个环节。
今天我们先谈一谈性能测试中的场景设计。
性能测试的场景设计
性能测试的场景如何定义?我们可以理解为功能测试中的用例,即性能测试的场景就是性能测试的用例。性能测试的场景是为了要实现特定的测试目标而对应用执行的压测活动。性能测试场景的设计与执行是整个性能测试活动的核心与灵魂,没有完整的场景设计就无法达到我们的测试目的,没有合理的场景设计就不会发现系统的性能缺陷。我们所开发的测试脚本,所预埋的测试数据都是为了实现特定场景所准备的。
一个性能测试场景包含诸多要素,图1中列出了一些必备的要素,其中测试模型作为测试场景的基础与输入。
图1 性能测试场景的组成要素
下面对每一个要素做一个简单的说明。
测试模型与测试指标
在进行场景设计之前我们应该先确定了本次性能测试的测试指标与测试模型。测试指标和测试模型是进行场景设计的前提和基础,是场景的输入。根据被测系统的类型不同,可能测试指标的类型略有不同。对于在线Web类的应用,测试指标一般包括在线用户数、最优并发用户数、最大并发用户数、交易平均响应时间、目标TPS等等。对于接口调用类的应用测试指标一般包括目标TPS、平均响应时间等。
测试模型就是被测试系统的各交易在线运行时承受的交易数量(或请求数量)的比例而不是并发用户的比例。为什么不是并发用户的比例呢?因为实际的用户的操作具有不确定性,使用测试工具很难模拟真实用户的行为。另外,在进行运营数据分析时很难获取用户的操作行为,而应用的交易记录却很容易通过查询的方式获取。应用实际承受的压力是用户的实际操作请求,在线用户如果没有进行实际操作那么他最多将消耗一个连接线程,而应用CPU并不会有什么资源消耗。100个用户平均每个花费10秒下一个订单和10个用户每1秒钟下一个订单对应用带来的压力是一样的。所以,在场景中能用最少的并发用户来模拟真实的请求是最经济的选择方式。
那么,测试模型到底该如何确定呢?通过需求调研获得。下面介绍的两点是我们常用的调研方式:
对于还未上线运营的新系统,我们一般会让应用的产品经理或负责人给出一个预估的比例;但是这个预估需要我们进行评估,不是随意的。对于一个以提供下单交易为主的应用,通常下单交易是占整个模型的较大比例,如果需求方提出的模型是查询比例较高,那么我们就有理由怀疑该模型的合理性。对于这种情况,我们建议选择几个常见的典型的模型来配合需求模型进行场景设计。
对于已上线运营的应用,我们一般会分析实际的交易数据来确定交易比例,这样会更加精准。例如一个应用对用户提供下单、查询、退款三个交易,我们通过DBA在线查询某日的交易数据总量为200000笔,其中交易下单160000笔、查询38000笔,退款2000笔,由此我们算出各交易的比例是80%、19%、1%,那么这个比例就是我们的测试模型。
被测交易或使用的脚本
测试脚本是测试场景的基础,脚本包括对应的测试数据,例如登录所需要的用户名与密码、下单交易可能需要的银行卡号等等。考虑到性能测试是多用户并发的测试,所以需要提前准备相应的测试数据,例如一个场景要对一个含登录操作的交易进行压测,那么我们在场景设计时就要考虑可用的用户名与密码数量;又如,要对退款交易做测试,那么就需要提前准备好可以退款的数据,这就需要提前做好数据预埋准备。
一般情况下,为了方便我们统计TPS,建议一个脚本只包含一个完整的交易,不要把多个交易放到一个脚本中。因为,不同的交易其响应时间会不同,响应时间较长的交易会成为“瓶颈”。另外,我们设计测试场景时需要考虑不同交易的占比,如果多个交易存在同一个脚本里,场景的设计就无法实现。
上文提到的“被测交易”是我们压测的对象,也是应用的入口。当然,并不是被测应用的每个交易都需要进行压测,这要视具体情况而定。如果被测应用提供的交易非常多,我们可以考虑只选取占比比较大的交易进行压测,而占比较低的交易可以忽略。
并发用户数量或并发线程数量
并发用户和并发线程其实是同一个概念,只是在不同的性能测试工具中其叫法不同而已。在下文中我们统称“并发用户”。当然,这些用户是虚拟用户,是压力测试工具使用进程或线程来模拟真实用户请求的一种方式。并发用户是每个场景提供不同压力的直接来源,场景不同其需要的并发用户数量可能会不同。那么是什么因素决定一个场景要并发用户的多少呢?主要是被测交易的响应时间和场景的目标TPS。交易响应时间的快慢是决定并发用户数量的主要因素,例如一个应用的某个交易响应时间是50ms,如果要实现100TPS的目标,那么只需5个并发用户即可达到(目标TPS*交易平均响应时间=并发用户量)。如果响应时间是100ms,那么实现同样的TPS需要的并发用户就会多一倍。
加压策略
加压策略就是并发用户以什么样的“步调”开始对应用发起请求。常用的并发策略有同时加载、指定间隔时间的加载,梯度加载等方式。加压策略的不同主要是模拟生产环境不同的情况,下面分别做简单介绍。
同时加载方式是指所有并发用户在场景启动时同时发起交易请求而不包含任何等待,这样会对被测应用带来突然的压力,用于考察应用在突然加压下的表现是否符合预期。一般有用户突增的业务特点的应用会设计这样的场景,例如,某些抢购系统、铁路售票系统的按时放票功能等。当然,对于那些并发用户较少的场景也可以采用这种用户加载方式。而对于有些应用如果同时加载大量的并发用户可能会出现异常或超时,导致部分并发用户失败。
指定间隔时间的加载方式是我们最常用的,这是为了模拟生产的实际情况,一般生产系统接收用户请求都是逐渐增加的,到当日交易的高峰时段达到最大。在场景设计时,根据并发用户的多少可以设置适当的增加频率,一般是“多长时间增加多少用户”。例如,每一秒钟增加一个用户、每两秒增加5个用户等等。
梯度加压策略也是我们常用的一种用户加载方式,但是这种方式严格来说应该是一种梯度加压场景。该场景一般是预先设置几个并发用户的梯度,每个梯度执行几分钟,这样就可以通过一个场景的执行基本上找到应用的最大TPS。在下文场景类型中,我们会详细介绍这种场景。
运行时间
每个类型的场景其执行时间是不同的。表1为大家提供一个参考值。运行时间是不包含用户的加载时间和退出时间的,即全部用户都在执行的这段时间。
表1 各种典型场景运行时间设置
延时方式
延时是上一笔请求完成到下一笔请求发起之间的时间间隔。延时在场景中的作用就是为了精准控制TPS,或者降低当前并发用户数量下的压力。而精准控制TPS的目的就是考察应用在特定压力下是否存在性能问题。在某些性能测试工具中提供了三种延时设置方式:
第一种是上一次请求完成后立即发起下一次请求,也就是延时为0。
第二种是上一次请求完成后间隔指定的时间后再发起下次请求。
第三种是在指定时间内完成一次请求,即区间型的延时,这要求我们设置的这个时间要大于交易的响应时间,也就是说要保证交易响应时间在我设置的这个时间的区间内,否则就不能实现精准控制TPS的目标。在这个区间内,交易响应时间无论如何变化,只要不突破我的这个最大区间,那么TPS就是平稳的。
在实际的场景设置中,为了实现精准的TPS控制目标,我们选用第三种设置方式。通过不断地尝试与调整,最终能够达到目标TPS。
用户终止方式
和用户加载方式对应,用户终止方式是场景执行完成后的用户退出方式。一般使用的是“同时退出”和“每隔多少时间退出几个用户”这种方式。这里我们重点介绍一下“同时退出”这种方式。应用在持续一段时间的压力后如果突然压力全部释放了,那么这时的应用在理想情况下应该是怎样的?CPU资源应该从繁忙立即变为空闲,网络传输也大幅降低,磁盘IO降为0等等。不然,那就是有某种问题的存在了。这时候就需要分析导致资源不能释放的原因。
各种资源的监控方式
资源的监控方式也是我们场景设计时必须考虑的一个必要因素,在场景设计时就应该确定每个场景的资源监控策略。这些策略包括监控的对象、使用的监控工具或方法、监控数据采集频率等。监控对象一般是测试环境中所有操作系统资源使用(CPU、内存、磁盘IO、网络吞吐等)、数据库(TOP SQL、数据库锁等待与死锁、缓冲区命中率等)、JVM的运行情况(堆内存垃圾回收、线程状态、数据库连接池使用情况等)等。监控数据采集频率也会因场景执行的时间长度不同而进行适当调整,例如混合容量场景如果执行30分钟,那么采集频率可以为每5秒钟采集一次,共采集360次。但是,考虑到监控要提前启动,所以采集次数可以适当增加一些,这样可以确保整个监控区间大于场景执行区间,也就同时监控到了资源使用在压力发起前后的变化情况。对于执行时间较长的场景,我们就要适当调整采集间隔和采集次数,例如对于一个执行12小时的稳定性场景,我们可以每50秒采集一次,共采集1000次。
常见的场景类型
单交易基准
一般使用一个用户或一个线程,延时设置为0,对一个交易持续运行10分钟以上。该场景的主要目的是获取单个交易在无压力的情况下的基准响应时间及环境资源使用情况,作为其他场景的参考依据。
单交易负载
单交易负载的场景是为了找到单个交易的最优TPS,检测单交易在并发情况下是否存在性能瓶颈。这个最优是以什么为衡量标准呢?通常以应用或数据库等系统的CPU使用率不大于70%为标准。为什么是70%?不能更高了吗?通常在生产上运行的应用,如果CPU使用率长期处于高水平那是非常严重的问题,应用的节点随时都可能挂掉。对于生产环境各种资源的使用情况,通常运维部门都会有实时的监控,一般当摸个节点的CPU使用率超过50%时就会触发报警,如果长时间处于高负载状态,那么说明应用节点可用资源不足,就应该考虑进行节点扩充了。
当然,也并不是什么情况下都需要找到单交易的最优TPS,这要分情况来对待。对于被测应用提供的交易比较少的话,可以通过不断测试找到每个交易的最优TPS。但是,有的应用提供的交易比较多,这时如果每个交易的最优TPS都要找到,那就会需要较多的时间来进行测试。
单交易负载的场景具体该如何设计与执行呢?如果你想找出每个交易的最优TPS,可以从5个并发用户开始,执行几分钟后再增加5个用户,直到应用CPU使用率超过70%为止。场景的延时设置为0,场景执行前需开启相关监控。该场景用于获取单交易在并发情况下的响应时间与TPS,发现交易本身是否存在并发问题,应用是否会出现错误和异常,响应时间相对单交易基准是否有明显的提高,资源使用率是否在合理的承受范围之内等等。如果应用存在性能缺陷该场景即可发现。
当然,如果你不想测试出每个交易的最优TPS,那么单独对每个交易做一次5个并发的负载测试即可。
多交易混合负载
多交易混合负载的目的是为了找到应用的最优TPS,即应用CPU资源消耗在70%左右时的TPS(此时需确保数据库等其他被调用资源不成为瓶颈)。
按照测试模型中的交易比例及目标TPS,对每个交易分配不同的并发用户数量,设置不同的延时,同时进行加压,通过多个子场景的不断尝试最终测试出应用能够达到的最优TPS。这个场景比较复杂,一般需要经过多次的测试与调整才能到达测试模型的比例要求。经过单交易负载测试之后我们已经获取了每个交易的平均响应时间,那么由此值我们便可以设置我们的混合负载场景。假设,我们应用的测试指标TPS为100,单交易负载测试获取的各交易响应时间如下:下单0.4秒,查询0.2秒,退款0.5秒,那么要达到100TPS的压力,该如何设置场景?
计算每个交易的TPS
下单TPS=100*80%=80,查询TPS=100*19%=19,退款TPS=100*1%=1
确定每个交易的并发用户
目标TPS、响应时间、并发用户之间有这样一个关系:
目标TPS=并发用户/响应时间
如果一个交易响应时间是0.2秒,那一个用户时的TPS就是1/0.2=5。
在咱们这个实例中每个交易的并发用户计算如下:
下单交易并发用户数量=80*0.4=32
查询交易并发用户数量=19*0.2=3.8
退款交易并发用户数量=1*0.5=0.5
大家看到了,这里出现了非整数的情况,怎么办?对于这种情况我们要进行整数化处理。即我们一般取大于并最接近当前数的整数,3.8我们按4,0.5我们按1。整数化后对应的响应时间也应该发生变化,否则就无法实现目标TPS。整数化再次计算实际的响应时间:
查询交易调整后的响应时间=4/19=0.21
退款交易调整后的响应时间=1/1=1
于是场景设置如下,下单交易并发用户32个延时设置为0秒,查询交易并发用户4个延时设置0.01秒,退款交易并发用户1个延时设置0.5秒,场景运行时间10分钟以上。但是这个场景运行结果可能并不会完全符合我们的预期,因为并发用户相比单交易负载场景已经增加了很多,交易的响应时间很可能会出现明显的延长。比如下单交易的实际响应时间可能会延长到0.6秒,那么实际的TPS将明显下降。如果出现这种情况该如何处理呢?我们推荐使用区间型延时设置,将这个“区间时间”设置的比实际交易响应时间大一些,根据这个时间再计算对应的并发用户量。另外,建议大家建一个excel的表格,用于计算延时和并发用户的值,效果见下表2。
表2 场景设置工具表
表2中的列“延时设置”的值是使用公式自动计算出来的,公式为“=并发用户单元格编号/(目标TPS单元格编号*交易占比单元格编号)”。建立这个表之后我们只需手动修改两个列的值就可以方便地计算出每个场景下的每个交易的延时,这两个列就是“平均响应时间”和“并发用户数”。平均响应时间随着并发用户的增加必然会相应地增长,所以在表2中每个场景的平均响应时间数据都是上个场景的执行结果。这样我们每执行完成一个场景,然后就把响应时间的数据填写到下个场景中,然后再修改并发用户数量,并确保延时设置大于平均响应时间即可,如果在测试执行过程中出现平均响应时间大于延时设置时间时需要停止场景重新计算。
综上所述,多交易混合负载场景并不是一个场景,而是一系列混合场景的集合。还以上例来说,目标100TPS时我们分析监控结果发现系统各项资源利用率都不是太高,这说明应用还能够承受更大的压力。这就需要我们继续加大压力进行测试。我们可能的场景是150TPS、200TPS等等。那么如何确定我们的压力梯度呢?这就要看系统资源到底使用了多少,如果100TPS时发现系统各项资源使用率在50%左右,我们就可以估计应用的最优TPS应该能够达到150,那么我们下一个场景就是要按150TPS的目标压力去发压,相关的并发用户和延时根据上表进行调整即可。如果不能实现150TPS的压力,那么我们就要减少目标TPS再进行发压,直到测试获取到应用的最优TPS。
多交易混合容量
容量的意思就是应用能够达到的最大TPS。该场景是和多交易混合负载场景相关联的,即通过多交易混合负载找出应用承受的最优TPS后继续对应用进行加压,直到找到应用的最大TPS。混合容量场景的并发用户与延时调节方式和混合负载一样,在这里就不再赘述了。
大并发
该类场景的目的是考察系统在大并发的情况下是否存在问题,是否有报错,是否有用户失败等。大并发一般要设置一个延时,用于到达最优并发时的TPS。那么,大并发时的用户到底设置多少,这个延时要设置多久,依据是什么呢?一般我们设置的并发用户数量是最优并发的5至10倍,而延时要通过计算得到。这里还是举例说明,有一个应用,测试得到的最大TPS为200,对应的并发用户为20,那么我们可以设置两个大并发场景,即100并发用户和200并发用户。100并发时的延时设置为100/200TPS=0.5秒,200并发时的延时设置为200/200TPS=1秒,这个延时为区间型的延时。
通常,在进行大并发测试时获得的TPS结果要比最大TPS低很多,因为在大并发时系统很有可能出现某些资源不够用,线程很可能会出现严重的阻塞等等。
如何考量大并发测试获得的测试结果是否符合预期,或者说大并发测试通过的标准是什么?这个也没有固定的标准可循,通常我们认为只要符合如下两方面的要求即可认为测试通过。
最大并发用户量是否能达到最大TPS时的5倍;
测试结果的TPS是否达到测试指标的要求;
需要说明的是这里的大并发和应用的最优并发与最大并发并不是一回事,二者并不相同。
稳定性
给应用一个恒定的压力,使场景运行较长的时间,用于测试应用在长时间运行下的表现,TPS是否有较大波动、是否有错误和异常、是否存在内存溢出等。根据业务类型不同一般会运行不同的时长,对于5*8这样的应用稳定性运行8小时即可,7*24这样的应用最好能够运行12小时以上。
恒定的压力怎么选取?通常有两种方式。第一种,选择应用最优压力的80%最为目标压力,这种方式比较适合应用的最优TPS不是很高的应用,比如200以下;第二种,如果应用的TPS比较高,那么我们需要换一种方式,否则就会产生较多的测试数据。例如一个应用的最优TPS为1000笔/秒,如果我们取其80%的压力800笔/秒,那么加压12小时的数据量为3456万!这时,我们使用200TPS的恒定压力运行12小时即可。
扩展性
考察应用的扩展能力。未扩展的情况下基本是一个子系统使用一个单独的机器节点,也就是应用的单点情况。扩展性就是,再对应用进行一个节点的扩展,测试扩展情况下的TPS。一般双节点的总TPS达到单节点的1.8倍即认为系统具有良好的扩展性。压测时我们选取混合容量场景中获取到应用最大TPS时的场景做为压测场景,并使用不同的压力机分别对两个节点进行加压,考察测试结果能够达到多少TPS。
可靠性或异常测试
这种情况下一般是将压力做为背景,对应用所依赖的环境进行模拟故障,考察应用的表现是否符合预期。例如,在一定压力背景下,模拟网络的闪断,待网络恢复后应用TPS是否能够及时恢复。背景压力我们一般选取混合负载测试获取最优TPS时的场景即可。
影响性
影响性测试也是性能测试过程中经常遇到一类场景。这种场景一般是针对提供非实时功能的应用所设计的。例如,有批处理或异步处理的应用。严格来说,这不应该算是一个单独场景类型,应该是一种特定的测试类型。对于这类的测试我们一般分两步来执行,首先是在未启用具有影响性的功能时测试出应用的最优和最大TPS;其次,启动具有影响性的功能,再按第一步的场景(场景的设置均不变)进行测试,对比二者的TPS差别,这个差别就是我们要考察的影响性。
挡板延时对比
如果压测环境使用了挡板,可以通过挡板来设置不同的延时进行对比测试。比如延时设置为0.5秒,1秒,甚至2秒。根据不同的延时设置,增加相应的并发用户数量,调整场景的各项设置,考察应用是否能够达到最大TPS,是否出现并发用户失败或应用异常等。对于挡板延时,一般的作用是模拟被调用的系统的延迟,考察被测应用在不同的延时情况下的性能表现。现在的应用系统很少有是完全独立的了,或多或少地都需要调用别的系统来实现某些操作或业务。例如,对于一个支付系统,起码需要调用银行通道、银联通道、手机短信通道等等第三方系统。由于受网络传输、被调系统的性能等多方面的影响,每次调用外围系统都会消耗一定的时间,综合起来我们一般会计算一个平均值,那么这个值就是被调用系统的平均延时。
在线用户
Web类的应用一般会有在线用户这样一个测试场景。这个场景主要的考察目标是在大量用户在线的情况下,系统是否会出现异常。在线用户即登录系统后并未执行任何操作的用户或执行操作后未退出的用户。脚本里设置一个足够长的思考时间,让用户反复执行“登录-在线-退出”这样的过程。一般这种场景模拟的用户数量较大。
最优并发用户
这个场景是为了找到应用的最优并发用户数量。最优并发用户数量是指应用达到最大TPS时的并发用户数量,这一点和最优TPS的定义是有区别的。通常在进行多交易混合容量场景执行过程中测试出应用最大TPS时的并发用户数量即为最优并发用户数量,故此场景可以和多交易混合容量场景合并执行。
最大并发用户
这个场景是为了找到应用能够承受的最大并发用户数量。最大并发用户数量是应用能够承受的并发用户的极限,这时要求用户不会出现失败,交易响应时间不能超过指标的要求,应用不会出现异常、错误等非正常现象。在测试过程中,当我们测试到最大TPS后继续增加并发用户数量,直到出现应用异常,或出现并发用户失败,或交易响应时间超过测试指标要求等,这时的并发用户数量即为最大并发用户。
对于最优并发用户或最大并发用户的场景,一般测试web类的应用或有明确并发用户指标需求的应用时会设计这样的测试场景,而接口类的应用一般不考虑这两个场景。
梯度加压
所谓梯度是指开始使用较少的用户加压一段时间(几分钟即可),待TPS稳定后再继续往上加用户,如此循环,直到TPS不再增加为止。整个过程就像爬楼梯一样,所以称为“梯度”。
这种类型场景一般是为了“偷懒”而设计的。比如,在生产环境要测试一个交易的最大TPS能够到多少时,我们为了节省宝贵的测试时间,一般会使用梯度加压的场景策略。这时我们不知道被测环境能够达到什么样的吞吐量,也没有明确的测试指标,为了快速找到应用的最大TPS,使用梯度场景是最简单有效的。另外,梯度场景适合独立交易的应用(压测场景只有一个交易),因为独立交易不必考虑复杂的场景设置,使用梯度场景可以节省大量的测试执行时间。