折扣爆料
折扣好货实时更新
大家工作中应该都面临过性能测试的任务,而如何做性能测试是一个非常广泛的问题。本文旨在分享对于一般性的互联网web网站的性能测试经验。以下将围绕这个问题进行深入的拆解和分析。
如何开展性能测试?相信对于不同阶段的测试人员,会有不同的答案。初学者可能会认为一款好用的压测工具会更快的帮助你完成性能测试任务,而对于有一定性能测试经验的人来说,制定一个完善的性能测试方案、编写可靠的性能测试脚本可能才是完成任务的关键。不管是压测工具的选择还是测试方案的制定,要开展一项性能测试任务,非常重要的一点是首先要先搞清楚测试的目的。
本次压测是为了验证系统能否撑得住高峰期的大流量?为了探索被测系统的最大负载?为后续的缩容扩容提供性能参考?还是为了验证某个场景的并发处理能力?还是为了验证新的版本是否满足性能基线?
不同的测试目的对应不同的性能测试策略,一个明确的测试目的是测试计划制定的必要条件。
根据测试目的,制定出详细的性能测试方案。包括性能压测工具的选择、压测环境的规划和准备、压测时间和人员等。
性能测试策略中需要明确压测模型、风险评估、性能监控方案、以及测试终止的条件和标准。其中压测模型是整个性能测试执行的核心,如果压测模型不够准确,可能会导致几天的压测工作白白浪费。
好了,以上几点解释了如何完成一项典型的性能测试任务,看起来比较简单,但其中每个细节想要做好可能会花费你几天甚至几个月的时间去了解和学习,接下来我们结合实战项目一个一个来分析。
以高峰期压测来举例,假如现在离高峰期还有两个月的时间,领导指派你一个任务:对xx系统做个性能压测,看今年高峰期能不能扛得住。接到这个任务后,先不要着急入手,先想一个问题:我们常说一个系统性能好还是不好,具体哪些指标才是衡量一个软件系统性能好坏的标准呢?
那么你知道被测系统目前的性能是好还是不好吗?我们首先要对被测系统有一个深刻的理解和认知,知己知彼才能百战不殆,如果你连被测系统目前是什么样的性能水平都不知道,如何能知道它扛不扛得住高峰期呢。
这也涉及到刚才提到的靠前点,先搞清楚测试的目的,本次的测试目的就是为了验证系统能否撑得住高峰期的大流量,我们又将这类性能测试叫做稳定性测试(也叫可靠性测试),通过给系统加载一定的业务压力,让系统持续运行一段时间,检测系统是否能够稳定运行。
我们先假设被测系统目前线上的性能表现良好(具体的实时性能指标可以通过各种监控平台去分析,比如应用监控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持续一段时间,下文会详细解释我们为什么不考虑并发数。在阅读下文之前可以先回顾下并发和吞吐量的概念和联系:
上文中我们了解到当前被测系统在主站2万峰值在线的情况下tps为800,平均响应时间为100ms,那么当前被测系统的并发数=800*0.1=80,那么为何我们不用并发用户数来衡量压测结果呢,我们为什么不直接用并发数80*10=800来作为高峰期压测的衡量指标?因为这里有一个很容易被忽视的点:响应时间对性能的影响。如果随着并发数的递增,平均响应时间是固定的,那么我们可以直接用并发数作为压测的指标,但实际上随着并发数的递增,平均响应时间是动态变化的。而且响应时间非常容易受影响,除了并发数增加时应用本身处理能力下降导致的响应时间变长之外,网络消耗、第三方服务依赖、甚至压测机的状态都会影响接口响应时间。如果以并发数作为压测的指标,你会发现同样的脚本多次运行时,每次的接口tps都不一样,最终导致服务器每次的压力也不一样,这样的测试结果往往不能反映真正的问题。
阿里云pts平台对并发模式和RPS模式的适用场景是这样写的:
正是因为并发模式的不稳定、难模拟和难预测的特性,使得并发模式只适用于性能瓶颈的定性分析,而不适用于服务器最大容量或最大负载的验证。但是受传统性能测试思路的影响,有接近90%的企业用户(数据来源于阿里云PTS) 将并发模式性能测试的结果作为稳定性、容量验收的依据,这是一件非常恐怖的事情。
性能测试方案里面任何一个决策都离不开具体业务,压测环境的选择也是同样的道理。到底是在测试环境做压测,还是在预发环境做压测,还是在生产环境做压测,或者是单独部署一套压测环境?如果单独部署一套压测环境,是采用完全复制生产环境,还是生产环境同配置的缩放,还是低配版的生产环境?我们先把“完全复制生产环境的压测环境”叫做“压测环境1”,“生产环境同配置的缩放”叫做“压测环境2”,“低配版的生产环境”等同于“测试环境”,接下来我们从以下维度一个一个去对比:
结合我们的业务实际情况,最终我们采用在生产环境做压测,原因如下:
当然,我们本次选择生产环境做压测也有一些局限性,比如不能长时间运行压测脚本,不能写入太多脏数据(压测写入的数据一定要做隔离,较好是有标记可以事后删除),压测完成后较好检查下服务器的状态是否健康。由于是在生产环境直接做压测,我们也无法登录太多真实用户,只能自己造一些测试账号。
我们选择jmeter作为压测工具,因为它学习成本低、免费、且与阿里云pts平台兼容,具体原因就不详细描述了。接下来就要进行压测脚本的编写,前面我们提到针对本次压测我们已经收集到被测系统排名前30的接口和每个接口预估的tps,除了流量排名靠前的接口以外,压测范围较好包含这几种业务场景:核心的业务场景、最耗性能的业务场景、出现过性能问题的业务场景,当然,所有的业务场景对应的接口都需要准确预估对应的tps。压测模型的业务范围确定之后,我们接下来就开始编写压测脚本吧(jmeter的具体用法本文不展开描述,有兴趣的可以自行baidu或查看官方文档):
注意:
压测脚本编写完成后可以先在本地调试好,再上传至阿里云进行压测: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查看服务器状态。总的来说,我们需要关注的性能指标包括:
理想情况下如果未出现性能瓶颈,本次测试就可以终止了。但实际情况中肯定不会这么顺利。我们在压测执行结束查看报告时会发现各种各样的问题,但是一般来说这些问题的最上层表现都是一样:接口成功率低,有大量报错。接下来肯定要分析报错原因:
这种对于测试人员来说相对简单,报错信息是服务器返回的,在脚本没有问题的情况下,就是服务出现性能瓶颈了(应用程序、网关、NG等都可能是瓶颈,要分析具体的报错原因),直接报给开发排查即可。
可能是达到了压测机的瓶颈,可能是压测机cpu瓶颈,也可能是压测机端口资源被占满,也可能是压测机带宽瓶颈等。如果是在本地做压测,可能要花费一些时间去排查具体原因具体解决,但是我们在阿里云平台做压测的话如果出现这种报错,直接增加施压机数量即可。
从实际的性能测试项目中可以发现,完成一项性能测试的一些关键核心的要素是以下几点: