RESAR性能工程中,场景分为基准、容量、稳定性、异常。每类场景对应不同目标。
基准场景是为找到系统中明显配置及软件Bug,也为容量场景提供可对比的基准数据。基准场景要有确定结论。
线程数应该如何确定,压力线程的连续递增的重要性,以及如何将之前所讲的分析思路应用在具体的分析案例中。
1 性能场景分类
通常拿到的需求:
- 评估系统能支持的最大容量。为知道当前的系统容量,目标很明确
- 测试并优化系统以支持线上业务。有优化必要
- 测试并评估未来几年内,性能容量是否满足业务发展。要求测试未来业务场景
把场景按照目标划分三类:
- 验证:评估当前系统容量
- 调优:评估并优化当前系统
- 推算:评估并推算未来系统容量
这种分类和我们一直强调的按类型分类(也就是基准、容量、稳定性、异常)的关系:
先确定性能场景目标,再设计对应具体场景。
对于图中的三种目标,位于下方的目标是包含它上方的目标的,比如以调优为目标的场景,包括了以验证为目标的场景。
1.1 按目标
按目标划分出的这三种性能场景,结合RESAR性能过程图:
1.1.1 性能验证(测试)
针对当前系统、模型、环境,验证版本是否有性能变化。这阶段中,不做复杂的性能监控,不做性能分析,不调优。
目前性能市场大部分项目都处于性能验证状态。若对一个已在线上稳定运行很久的系统,去做版本更新的验证倒无可厚非,只要比对下数据。这种项目周期通常在一两周内,不会更长,且也不用更长,除非有大性能瓶颈。
性能验证的项目,很多人一直在做“性能场景执行”和“性能结果/报告”这两步。其他步也不是不做,只是会拿之前文档做个修改,走个过场,想着反正也没人看。所以,性能验证项目就变成:来个版本,用同样脚本、环境、数据,执行一遍。
这样的执行多了后,你会产生误解:原来性能就是这样无聊地重复一轮轮执行,很多人都是在这样项目中认识性能,从而认为自己的技术还挺好,觉得性能也不难嘛。
1.1.2 性能调优
针对当前系统、模型、环境,做性能监控、性能分析和性能优化,并给出具体结论。这是大部分项目都应做到,但实际没做到的。
若一个项目要给出“系统上线后以什么样容量能力运行”这样的结论,那这场景目标的细化相当关键。
很多性能项目最缺少的就是给明确结论。什么叫“给结论”?写TPS多少、CPU使用率多少,叫结论吗?这不叫结论。结论应该有业务含义,如支持1000万用户在线、支持1万用户并发等,这叫结论。
不管你给多少TPS,只要老板或是其他人问:“那我上1000万用户后,系统会死吗?”你知道咋回答?给人感觉,你这性能做得没具体价值。
性能如何体现价值?
我说,我做的项目,我会给承诺:我执行的性能场景范围内,我要保证线上不会死。死了,我觉得这性能项目就不该收费。
像你买个手机,回来一用,发现打不了电话,这时咋办?退货换货还生气。
那做性能为何就给不了这样承诺?若你做完个项目,却不能告诉对方这系统能不能好好活着,那人家要你干嘛,直接砍掉这项目就好,还省成本。
从RESAR性能工程的过程图来看,对性能调优的项目,需完成从“性能需求指标”到“生产运维”的整个过程。这整个过程不是走过场,而是每步都要精雕细琢。
1.1.3 性能推算
性能估算针对的是未来的系统、模型、环境,要对此做出严谨的业务增长模型分析,并在场景执行过程中进行性能监控、分析和优化,同时给出具体的结论。很多项目都想做到性能估算,可往往都只走过场。
性能估算的场景目标中,如要估算未来时间不远,根据业务的发展趋势的确可推算,并且也是合理场景。就怕狮子大开口需求,一说到估算,就是系统十年不宕机。
性能估算项目,也要完成从“性能需求指标”到“生产运维”整过程。有两个环节与性能调优项目中的不同:“性能需求指标”和“性能模型”。
在性能估算项目中,性能需求指标和性能模型一定不是由性能测试人员来决定的,而是由整个团队来决定。上到老板,下到基层员工,都要有统一的认识。要不然等项目做完了之后,你就无法回答老板那个“能不能支持1000万在线“的问题。
1.1.4 小结
1.2 按过程分类
“过程”就是我们应该怎样执行性能场景、性能场景应该从哪里开始的问题:
这四种场景执行过程:
- 基准场景
- 容量场景
- 稳定性场景
- 异常场景
性能场景中需要且仅需要这四种场景。
正式的性能场景(要给出结果报告的性能场景),关键词:“递增”和“连续”。在性能场景中一定要做到的。因为生产环境没有不连续情况,并且在生产环境中,用户量肯定由少到多、有起伏变化。也只有这两个关键词能把场景的基调给定下来。
1.2.1 基准场景
对系统完全不了解时,先要清楚系统大概容量能力,从哪开始呢?基准场景。
如电商系统,测试11个业务。一上来就把这11个业务脚本做出来,上去压?肯定不行,因为还不知道每个业务能跑多大TPS,有无性能瓶颈。直接混合压,会导致多个性能问题一起暴露并相互影响,难以分析。
所以,先做单接口的基准场景。
先做“单接口的基准场景”,这的单接口在jmeter脚本中是否可理解为一个线程组下面只有一个HTTP请求?若是,那对于那种有上下关联参数的接口,个别入参只能使用一次的情况怎么解决?提前造足够的数据。
① 具体咋做?
拿几个用户测试登录接口的基本性能(这尝试过程本身不是基准场景):
可见1个压力线程大概产生20TPS。
单接口的容量达到多少才不影响混合的容量场景?
若这是单登录接口,须高过50TPS。而我们现在用的是8C 16G,根据CRUD测试经验,即使不走缓存,这样操作要达到500TPS没啥问题。
在一个线程能产生20 TPS前提下,先假设接口能达最大500 TPS都是线性的,就需:
因1个压力线程大概产生20 TPS,从TPS曲线看还是上升较快,所以考虑把Duration(场景的持续时间)放长,让压力不要增加太快,而在这缓慢增加过程中观察曲线变化,以判断后续动作及最大容量。我会这样来确定场景的加压过程。
在图中,我上到了30个线程,这里也可以不要高出那么多,只要高出25个线程就可以了。我把Ramp-up period设置为600秒,也就是20秒上一个线程,这样就会产生一个明显的连续递增的过程。
② 思路总结
- 先确定单线程运行时的TPS值
- 根据系统最大的预估容量,设置场景中的线程数、递增参数等。若你不会预估容量,可直接多加一些线程,然后在递增过程中查看曲线变化
- 确定正式基准场景的压力参数
当然,对于这个过程,也要在测试过程不断修正。
③ 基准场景的目的
-
获得单接口最大TPS:如果单接口最大TPS没有超过容量场景中的要求,那就必须要调优。如某容量场景的目标TPS 100,里面包含某单接口的调用,那这单接口的基准场景测试的TPS就不应低于100。
若超过了,是否就无需调优了呢?再看第二目的。 - 解决单接口基准场景中遇到的性能问题:做单接口测试时,碰到性能瓶颈一定要分析,这就涉及性能分析逻辑。
所以,性能分析基本分为两阶段:
- 第一阶段:硬件资源用完。基准场景中,要把CPU、内存、网络、IO等资源中的任一耗尽,因为此时易从全局监控的性能计数器看到现象,可以接着去跟踪分析
- 第二阶段:优化到最高TPS。基准场景中要把单接口TPS调到最高,以免成为容量场景中的瓶颈点
若第一阶段目标达不到,肯定要找瓶颈点:
- 若硬件资源已用完,TPS也满足容量场景的要求,从成本考虑,这项目无需再继续
- 若硬件资源用完,但TPS没满足容量场景的要求,须优化
执行一个单接口场景,将上面思路落地。
2 登录接口实战
按基准场景的设计步骤,先试运行接口的基准场景。
基准测试中,试运行只为看下基本的接口响应时间,并非为完成基准场景:
满目疮痍!虽场景执行时间不长,但10个线程上来就报错,响应时间、TPS也达到失望程度,仅12.5TPS,咋办啊?只能分析它!来看如何将性能分析思路落地。
你肯定好奇,报错是报啥错了呢?我认为应先跑下单接口,测试单接口的响应时间(虽然上10个线程也能暴露问题),但一看单接口响应时间就5s+,应该先解决这个问题,再上压力也不迟。
报错就是没断言到“成功”。解决的就是响应时间的问题呀。不解决问题响应时间怎么会下来呢。
2.1 问题现象
如图所示,现象不言而喻。
2.2 分析过程
按RESAR性能分析逻辑,针对响应时间长,先要做拆分时间。通过SkyWalking看时间浪费在哪:
一个Token的SelfDuration居然要5s多!开源项目坑就是多。看起来功能似乎都实现,Star好几万,但完全没性能。既然Token接口响应时间长,在SkyWaking又看不到完整调用栈,接下来就有两个动作:
- 打印一个完整栈,看调用链路
即使看到调用链路,也还是要跟踪具体方法的耗时,只有这样才能把证据链走下去 - 不打印栈,直接连到Java进程,看方法时间消耗
直接用该法
看方法时间消耗,像JDB/JvisualVM/Arthas这些工具都可。我用Arthas跟踪。
先跟踪Token方法。
trace com.dunshan.mall.auth.controller.AuthController postAccessToken '#cost > 1000' -n 3
trace org.springframework.security.oauth2.provider.endpoint.TokenEndpoint postAccessToken '#cost > 1000' -n 3
trace org.springframework.security.oauth2.provider.token.AbstractTokenGranter getOAuth2Authentication '#cost > 1000' -n 3
trace org.springframework.security.authentication.AuthenticationManager getOAuth2Authentication '#cost > 500' -n 3
trace org.springframework.security.authentication.ProviderManager authenticate '#cost > 500' -n 3
trace org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider authenticate '#cost > 500' -n 3
用上面语句层层跟踪,最终到:
其他工具也可达类似效果,别迷恋工具。
既然这authenticate方法耗时比较长,就打开源码看这段:
Debug进去:
原来,这里是个加密算法BCrypt。
2.3 优化方案
Bcrypt加密时,每次HASH出的值不同,且特慢!用更快的加密方式或去掉这加密算法。
先去掉该加密算法,继续往下走。
2.4 优化效果
同样线程数,现TPS从20涨到80。
可见,通过响应时间的拆分跟踪,知道哪个方法慢,再分析该方法,确定解决方案。
这是最简单的RESAR性能分析七步法应用,似乎分析过程跳过了七步法中的分析架构图这种步骤?实际上在我们分析过程中,也离不开,因为不管看架构图,还是看调用链,都要在脑子中有架构逻辑。
3 总结
根据RESAR性能工程理论,在性能场景中,按执行过程,将场景分类,这些场景各有目的。基准场景的重要目的:
- 获得单接口最大TPS
- 解决单接口基准场景中遇到的性能问题
这两个目的对我们很重要,都是为了容量场景打基础的。
感受性能分析过程。最后的这个优化效果其实还没有达到对性能的要求。后面将看到更多分析逻辑。
4 FAQ
如果这是一个单登录接口,就必须高过 150TPS,这是最起码的。而我们现在用的是 8C16G 的机器,根据 CRUD 的测试经验,即使不走缓存,这样的操作要达到 500TPS 应该没什么问题。高过150TPS和500TPS怎么来的?
150TPS应写为50TPS,跟业务模型中的数据一致才是。
500是根据经验来的。8C 16G,若是写操作,达到500TPS应该没问题。若是读操作,还会更高,应能达1000TPS以上。
基准测试到底是测接口or测单业务?
看制定的场景目标。容量场景是为模拟被测系统的生产场景。在这之前都放到基准场景中做。 所以按我的逻辑就是,基准场景中是:1, 先测单接口;2. 后测单业务。这两个都放在基准场景中。 由单业务组成的线上真正场景,应该放到容量场景中做。
利用计算公式,利用在线用户数等得到的请求级线程数是为了回答TPS、并发用户、在线用户之间的关系的。
基准场景中,压力线程数通过预估或者直接不断加大线程数得到单接口最大TPS,那个计算的线程数是压测过程中作何用?压力线程预估是为了在实际执行场景过程中来判断的。
基准测试,先测出每个接口单线程的TPS,再根据评估的单接口容量计算要多少线程,最后计算出的线程设置单接口的性能测试?
对压力工具这边的操作,是这样的。不过基准场景中,还要监控分析。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net