当前位置:喜价首页攻略科技数码性能测试和压力测试,性能压力测试怎么做?

性能测试和压力测试,性能压力测试怎么做?

概要

大家工作中应该都面临过性能测试的任务,而如何做性能测试是一个非常广泛的问题。本文旨在分享对于一般性的互联网web网站的性能测试经验。以下将围绕这个问题进行深入的拆解和分析。

如何开展性能测试?相信对于不同阶段的测试人员,会有不同的答案。初学者可能会认为一款好用的压测工具会更快的帮助你完成性能测试任务,而对于有一定性能测试经验的人来说,制定一个完善的性能测试方案、编写可靠的性能测试脚本可能才是完成任务的关键。不管是压测工具的选择还是测试方案的制定,要开展一项性能测试任务,非常重要的一点是首先要先搞清楚测试的目的。

  1. 分析性能测试的目的。

本次压测是为了验证系统能否撑得住高峰期的大流量?为了探索被测系统的最大负载?为后续的缩容扩容提供性能参考?还是为了验证某个场景的并发处理能力?还是为了验证新的版本是否满足性能基线?

不同的测试目的对应不同的性能测试策略,一个明确的测试目的是测试计划制定的必要条件。

  1. 制定性能测试方案。

根据测试目的,制定出详细的性能测试方案。包括性能压测工具的选择、压测环境的规划和准备、压测时间和人员等。

  1. 制定性能测试策略。

性能测试策略中需要明确压测模型、风险评估、性能监控方案、以及测试终止的条件和标准。其中压测模型是整个性能测试执行的核心,如果压测模型不够准确,可能会导致几天的压测工作白白浪费。

  1. 测试脚本执行。
  2. 性能测试结果分析。
  3. 性能优化-回归(性能优化涉及到的篇幅更大,本文不展开讨论)

好了,以上几点解释了如何完成一项典型的性能测试任务,看起来比较简单,但其中每个细节想要做好可能会花费你几天甚至几个月的时间去了解和学习,接下来我们结合实战项目一个一个来分析。

实战-高峰期压测

以高峰期压测来举例,假如现在离高峰期还有两个月的时间,领导指派你一个任务:对xx系统做个性能压测,看今年高峰期能不能扛得住。接到这个任务后,先不要着急入手,先想一个问题:我们常说一个系统性能好还是不好,具体哪些指标才是衡量一个软件系统性能好坏的标准呢?

  • 吞吐率 —— 系统单位时间内处理的请求数,广义上的tps、rps、qps
  • 响应时间 —— 服务器响应时间+客户端响应时间+网络消耗时间
  • 资源占用 —— 系统正常运行时的cpu占用、内存占用、磁盘I/O、网络I/O、连接数、线程数等
  • 并发用户数 —— 反应软件系统的并发处理能力

那么你知道被测系统目前的性能是好还是不好吗?我们首先要对被测系统有一个深刻的理解和认知,知己知彼才能百战不殆,如果你连被测系统目前是什么样的性能水平都不知道,如何能知道它扛不扛得住高峰期呢。

这也涉及到刚才提到的靠前点,先搞清楚测试的目的,本次的测试目的就是为了验证系统能否撑得住高峰期的大流量,我们又将这类性能测试叫做稳定性测试(也叫可靠性测试),通过给系统加载一定的业务压力,让系统持续运行一段时间,检测系统是否能够稳定运行。

流量预估

我们先假设被测系统目前线上的性能表现良好(具体的实时性能指标可以通过各种监控平台去分析,比如应用监控PinPoint、听云平台和zabbix服务器监控),那么新的问题又来了,“通过给系统加载一定的业务压力”里面的“一定”到底是多少呢?这涉及到一个非常重要的问题:流量预估。这里的流量不单是指多少uv、pv,而是通过一些计算最终将数据转换为预估的系统吞吐量甚至某接口的吞吐量。

这些数据我们从哪来?刚才说到要对被测系统有一个深入的了解,要先知道被测系统在当前压力下总共有多少台应用服务器,多少台数据库服务器,涉及到哪些中间件服务器,网站每天的峰值在线人数是多少,每天的峰值吞吐量是多少,被测系统所提供的接口服务哪些流量大,哪些流量小,流量最大的接口峰值吞吐量是多少,系统平均响应时间是多少,甚至哪些接口在读库,哪些接口走了缓存,哪些接口走了消息队列,缓存策略是什么,数据库的分库分表逻辑是什么,这些问题都需要在压测之前搞清楚,并且需要准确体现在压测模型中。

我们一个一个来收集这些数据:假设我们从运维平台了解到当前应用服务器有8台,数据库服务器有3台(一主两从,读写分离),从开发和运维那里了解到被测系统涉及到的中间件有redis、kafka等,从主站在线人数统计图表中了解到最近网站的峰值在线人数是2万,从听云平台或者PinPoint上了解到被测系统每天的峰值tps是800,系统平均响应时间是100ms,从kibana的ng日志里面可以分析出被测系统所提供的接口流量最大的a接口的峰值tps是200,b接口峰值tps是100,尽可能多的统计出流量排名靠前的接口,假设我们已经统计出前30个接口的峰值tps,且被测系统所提供的各个接口响应时间差别不大(实际情况要比本次假设的理想情况复杂的多,可能某个流量小的慢接口就把整个系统的性能拖垮了,本次先不对这种情况做讨论)。

系统当前的性能相关数据有了,那么我们以多少流量作为压测时的数据呢?上面的数据是在网站峰值人数2万时收集的,要得到压测的流量数据,我们需要从外部获取到一个数据:高峰期网站的峰值在线人数预估值。已知市场和运营预估高峰期大概峰值在线人数会达到20万(是目前的10倍),那么我们预估在网站在线人数峰值20万的情况下,被测系统的峰值tps会达到800*10=8000,按照比例计算a接口的峰值tps会达到2000,b接口1000(其他接口也同样*10)。所以我们高峰期预估的情况是系统会在tps8000的情况下稳定运行,一般来说稳定性测试需要支持峰值负载的1.5倍到2倍的流量下运行,也就是说我们压测的目标tps是12000~16000。

并发模式与吞吐量模式

注意上文在进行流量预估时,我们采用系统的tps当成最终压测时的衡量指标,也就是说我们期望被测系统稳定运行在tps12000以上持续一段时间,而不是并发800持续一段时间,下文会详细解释我们为什么不考虑并发数。在阅读下文之前可以先回顾下并发和吞吐量的概念和联系:

  • 并发数:即虚拟用户数,对应Loadrunner 里面的uv,jmeter里面的线程组。
  • 吞吐量:系统每秒钟处理的请求数,与tps、qps、rps一个意思。
  • 并发数=tps*响应时间

上文中我们了解到当前被测系统在主站2万峰值在线的情况下tps为800,平均响应时间为100ms,那么当前被测系统的并发数=800*0.1=80,那么为何我们不用并发用户数来衡量压测结果呢,我们为什么不直接用并发数80*10=800来作为高峰期压测的衡量指标?因为这里有一个很容易被忽视的点:响应时间对性能的影响。如果随着并发数的递增,平均响应时间是固定的,那么我们可以直接用并发数作为压测的指标,但实际上随着并发数的递增,平均响应时间是动态变化的。而且响应时间非常容易受影响,除了并发数增加时应用本身处理能力下降导致的响应时间变长之外,网络消耗、第三方服务依赖、甚至压测机的状态都会影响接口响应时间。如果以并发数作为压测的指标,你会发现同样的脚本多次运行时,每次的接口tps都不一样,最终导致服务器每次的压力也不一样,这样的测试结果往往不能反映真正的问题。

阿里云pts平台对并发模式和RPS模式的适用场景是这样写的:

  • 并发模式适用场景:如果需要从客户端的角度出发,摸底业务系统各节点能同时承载的在线用户数,可以使用该模式设置目标并发。
  • rps模式适用场景:RPS模式即“吞吐量模式”,通过设置每秒发出的请求数,从服务端的角度出发,直接衡量系统的吞吐能力,免去并发到RPS的繁琐转化,一步到位。

正是因为并发模式的不稳定、难模拟和难预测的特性,使得并发模式只适用于性能瓶颈的定性分析,而不适用于服务器最大容量或最大负载的验证。但是受传统性能测试思路的影响,有接近90%的企业用户(数据来源于阿里云PTS) 将并发模式性能测试的结果作为稳定性、容量验收的依据,这是一件非常恐怖的事情。

压测环境的选择

性能测试方案里面任何一个决策都离不开具体业务,压测环境的选择也是同样的道理。到底是在测试环境做压测,还是在预发环境做压测,还是在生产环境做压测,或者是单独部署一套压测环境?如果单独部署一套压测环境,是采用完全复制生产环境,还是生产环境同配置的缩放,还是低配版的生产环境?我们先把“完全复制生产环境的压测环境”叫做“压测环境1”,“生产环境同配置的缩放”叫做“压测环境2”,“低配版的生产环境”等同于“测试环境”,接下来我们从以下维度一个一个去对比:

  • 测试结果的准确性:生产环境 > 压测环境1 > 压测环境2 = 预发环境 > 测试环境
  • 部署/维护成本:压测环境1 > 压测环境2 > 生产环境 = 预发环境 = 测试环境
  • 安全性(对网站用户风险从低到高): 压测环境1 = 压测环境2 = 测试环境 > 预发环境 > 生产环境

结合我们的业务实际情况,最终我们采用在生产环境做压测,原因如下:

  1. 生产环境就是用户使用的环境,生产环境的性能结果能最准确的反映真实情况
  2. 生产环境凌晨用户量极少,后半夜对网站做压测对用户的影响可以忽略
  3. 相比生产环境,单独的压测环境部署成本和维护成本都较大(长期来看肯定是“完全复制生产环境的压测环境”是最优选择,但是考虑到实际情况和任务周期,先暂时采用生产环境直接压测的方式)

当然,我们本次选择生产环境做压测也有一些局限性,比如不能长时间运行压测脚本,不能写入太多脏数据(压测写入的数据一定要做隔离,较好是有标记可以事后删除),压测完成后较好检查下服务器的状态是否健康。由于是在生产环境直接做压测,我们也无法登录太多真实用户,只能自己造一些测试账号。

压测模型/压测脚本

我们选择jmeter作为压测工具,因为它学习成本低、免费、且与阿里云pts平台兼容,具体原因就不详细描述了。接下来就要进行压测脚本的编写,前面我们提到针对本次压测我们已经收集到被测系统排名前30的接口和每个接口预估的tps,除了流量排名靠前的接口以外,压测范围较好包含这几种业务场景:核心的业务场景、最耗性能的业务场景、出现过性能问题的业务场景,当然,所有的业务场景对应的接口都需要准确预估对应的tps。压测模型的业务范围确定之后,我们接下来就开始编写压测脚本吧(jmeter的具体用法本文不展开描述,有兴趣的可以自行baidu或查看官方文档):

  1. 添加线程组
  2. 添加各个http请求以及相应的响应断言
  3. 为每个http请求添加对应的吞吐量控制器
  4. 添加http信息头管理器、用户定义的变量,根据实际情况添加至需要的目录层级
  5. 添加setup线程组,用来做登录取token(依次用到json提取器、beanshell后置处理程序设置全局变量)
  6. 设置每个接口的吞吐量(吞吐量控制器设置的值是百分比)
  7. 本地调试

注意:

  • 响应断言一定要添加,因为某些接口报错时http响应码是正常的,如果不添加响应断言可能无法捕获到报错的接口。
  • setup登录取token时不要写死用户名和密码,建议用户名和密码用csv文件进行存储,上传csv时选择“切分文件”,可以避免分布式压测时不同的压测机登录互踢的情况。
  • 压测脚本产生的压力一定要最接近真实情况,必须考虑缓存、分库分表等情况,如果某个查询接口压测时一直在读缓存或者一直在查询某个分表,最终的测试结果就没什么意义了。
  • 压测使用的用户账号的一些基础数据也必须与线上真实用户的情况保持一致,比如要压测作业列表的接口,肯定不能造一个作业列表只有几条数据的账号去压测,也不能找一个作业列表有几千条数据的账号去做压测。

压测脚本编写完成后可以先在本地调试好,再上传至阿里云进行压测:pts平台→创建压测→Jmeter压测→场景配置(上传jmeter脚本文件和csv文件)→施压配置→保存

在进行到施压配置的时候,需要填写并发数,可能有些人会有疑问,我们上文刚讲过本次是采取tps模式,为什么还要设置一个并发数?没有什么理由,因为jmeter压测必须要设置一个并发数(也就是线程组的线程数),但是此处设置的并发数只是为了将压力调整到我们期望的值,并没有其他特殊的含义。例如本次测试中上文提到我们期望服务器在tps=12000以上稳定运行,如果随着并发数的增加,响应时间100ms变化不大的情况下,此时的并发数大概等于12000*0.1=1200,也就是我们最大的并发数可以先设置为1200,流量模型设置为均匀递增,在调试阶段观察总的tps峰值能否达到12000(通过压测报告里面的图表可以查看压测机产生的实时tps)。如果通过压测报告查看tps最终达不到12000,那么就继续逐步加大并发数。

也可以不使用本地jmeter脚本,直接在pts平台创建pts场景进行压测。pts场景的优势是可以直接选择RPS模式,不需要再自己设置并发数去不断调试到自己期望的压力。考虑到脚本编写的时间成本和调试时的费用,本次测试依旧采用直接上传jmeter脚本的方式。

由于是在生产环境做压测,出于安全考虑,调试压测脚本时也尽量选在凌晨没有用户的时候。且在并发数均匀递增运行期间一定要做好服务器的监控,如果执行过程有出现一些异常(服务器状态异常、应用程序异常、数据库异常、其他中间件异常等),要靠前时间考虑是否需要停止压测。

压测执行/报告分析

经过几次调试后,将并发数设置成刚好能达到期望的tps区间12000~16000,就可以开始正式执行压测脚本了。运行时长建议设置为20min,并发递增时长设置为5分钟,运行多次对比查看平均值。可能会有人问这里为什么不直接将运行时长设置的长一点,运行一次就好了?原因是我们虽然最终是以tps模式来衡量服务器压力和最终的测试结果,但是jmeter压测执行时只能设置一个并发数,我们并不能保证调试阶段设置的并发数能每次都达到期望的tps。

好了,执行过程没什么特殊的,监控好网站运行状态就可以了。重点是在报告分析,pts平台提供了友好的压测报告展现,具体样式本文不做贴图了,可以登录阿里云平台一边查看pts报告样例一边看下文。我们需要关注报告里整体的tps、成功率以及单接口的tps、成功率、平均响应时间,tps如果未达标但与期望相比差距不大,可以查看详情里面5分钟之后的tps是否维持在期望值以上,因为前5分钟并发数还在递增,tps也是一个递增的过程。

除此之外,我们还要关注服务端的状态,压测过程中需要监控应用状态(可用听云平台或pinpoint平台),zabbix查看服务器状态。总的来说,我们需要关注的性能指标包括:

  • 压测接口状态:响应时间、tps、成功率等
  • 应用程序状态:连接数、线程数、异常日志等
  • 服务器状态(包括应用服务器、数据库等):cpu、连接数、内存等

理想情况下如果未出现性能瓶颈,本次测试就可以终止了。但实际情况中肯定不会这么顺利。我们在压测执行结束查看报告时会发现各种各样的问题,但是一般来说这些问题的最上层表现都是一样:接口成功率低,有大量报错。接下来肯定要分析报错原因:

  1. 报错信息是服务器返回的:

这种对于测试人员来说相对简单,报错信息是服务器返回的,在脚本没有问题的情况下,就是服务出现性能瓶颈了(应用程序、网关、NG等都可能是瓶颈,要分析具体的报错原因),直接报给开发排查即可。

  1. 报错信息是jmeter抛出的:

可能是达到了压测机的瓶颈,可能是压测机cpu瓶颈,也可能是压测机端口资源被占满,也可能是压测机带宽瓶颈等。如果是在本地做压测,可能要花费一些时间去排查具体原因具体解决,但是我们在阿里云平台做压测的话如果出现这种报错,直接增加施压机数量即可。

总结

从实际的性能测试项目中可以发现,完成一项性能测试的一些关键核心的要素是以下几点:

  1. 一定要深入理解业务、理解被测系统,性能测试中任何决策都离不开具体的业务,大到压测环境的选择、压测流量的预估,小到压测脚本中的一个参数的设置,都需要与真实的业务场景紧密联系。
  2. 明确测试的目的,性能测试中的一系列策略全部都是以最终测试目的为导向,压测过程中始终明确测试目的,才能做出最有效的测试方案。
  3. 压测模型一定要足够准确,其中包括压测范围、压测脚本设计等,一个足够准确的压测模型得出的结果才具有价值。
全部评论(0)