如何设计高效的基准场景?揭秘大厂的实战策略!

简介: RESAR性能工程中,场景分为基准、容量、稳定性、异常。每类场景对应不同目标。基准场景是为找到系统中明显配置及软件Bug,也为容量场景提供可对比的基准数据。基准场景要有确定结论。

RESAR性能工程中,场景分为基准、容量、稳定性、异常。每类场景对应不同目标。


基准场景是为找到系统中明显配置及软件Bug,也为容量场景提供可对比的基准数据。基准场景要有确定结论。


线程数应该如何确定,压力线程的连续递增的重要性,以及如何将之前所讲的分析思路应用在具体的分析案例中。


1 性能场景分类


通常拿到的需求:


评估系统能支持的最大容量。为知道当前的系统容量,目标很明确

测试并优化系统以支持线上业务。有优化必要

测试并评估未来几年内,性能容量是否满足业务发展。要求测试未来业务场景

把场景按照目标划分三类:


验证:评估当前系统容量

调优:评估并优化当前系统

推算:评估并推算未来系统容量

这种分类和我们一直强调的按类型分类(也就是基准、容量、稳定性、异常)的关系:




先确定性能场景目标,再设计对应具体场景。


对于图中的三种目标,位于下方的目标是包含它上方的目标的,比如以调优为目标的场景,包括了以验证为目标的场景。


1.1 按目标

按目标划分出的这三种性能场景,结合RESAR性能过程图:

13.jpeg



1.1.1 性能验证(测试)

针对当前系统、模型、环境,验证版本是否有性能变化。这阶段中,不做复杂的性能监控,不做性能分析,不调优。


目前性能市场大部分项目都处于性能验证状态。若对一个已在线上稳定运行很久的系统,去做版本更新的验证倒无可厚非,只要比对下数据。这种项目周期通常在一两周内,不会更长,且也不用更长,除非有大性能瓶颈。


性能验证的项目,很多人一直在做“性能场景执行”和“性能结果/报告”这两步。其他步也不是不做,只是会拿之前文档做个修改,走个过场,想着反正也没人看。所以,性能验证项目就变成:来个版本,用同样脚本、环境、数据,执行一遍。


这样的执行多了后,你会产生误解:原来性能就是这样无聊地重复一轮轮执行,很多人都是在这样项目中认识性能,从而认为自己的技术还挺好,觉得性能也不难嘛。


1.1.2 性能调优

针对当前系统、模型、环境,做性能监控、性能分析和性能优化,并给出具体结论。这是大部分项目都应做到,但实际没做到的。


若一个项目要给出“系统上线后以什么样容量能力运行”这样的结论,那这场景目标的细化相当关键。


很多性能项目最缺少的就是给明确结论。什么叫“给结论”?写TPS多少、CPU使用率多少,叫结论吗?这不叫结论。结论应该有业务含义,如支持1000万用户在线、支持1万用户并发等,这叫结论。


不管你给多少TPS,只要老板或是其他人问:“那我上1000万用户后,系统会死吗?”你知道咋回答?给人感觉,你这性能做得没具体价值。


性能如何体现价值?

我说,我做的项目,我会给承诺:我执行的性能场景范围内,我要保证线上不会死。死了,我觉得这性能项目就不该收费。


像你买个手机,回来一用,发现打不了电话,这时咋办?退货换货还生气。


那做性能为何就给不了这样承诺?若你做完个项目,却不能告诉对方这系统能不能好好活着,那人家要你干嘛,直接砍掉这项目就好,还省成本。


从RESAR性能工程的过程图来看,对性能调优的项目,需完成从“性能需求指标”到“生产运维”的整个过程。这整个过程不是走过场,而是每步都要精雕细琢。


1.1.3 性能推算

性能估算针对的是未来的系统、模型、环境,要对此做出严谨的业务增长模型分析,并在场景执行过程中进行性能监控、分析和优化,同时给出具体的结论。很多项目都想做到性能估算,可往往都只走过场。


性能估算的场景目标中,如要估算未来时间不远,根据业务的发展趋势的确可推算,并且也是合理场景。就怕狮子大开口需求,一说到估算,就是系统十年不宕机。


性能估算项目,也要完成从“性能需求指标”到“生产运维”整过程。有两个环节与性能调优项目中的不同:“性能需求指标”和“性能模型”。


在性能估算项目中,性能需求指标和性能模型一定不是由性能测试人员来决定的,而是由整个团队来决定。上到老板,下到基层员工,都要有统一的认识。要不然等项目做完了之后,你就无法回答老板那个“能不能支持1000万在线“的问题。


1.1.4 小结

12.jpeg


1.2 按过程分类

“过程”就是我们应该怎样执行性能场景、性能场景应该从哪里开始的问题:


11.jpeg


这四种场景执行过程:


基准场景

容量场景

稳定性场景

异常场景

性能场景中需要且仅需要这四种场景。


正式的性能场景(要给出结果报告的性能场景),关键词:“递增”和“连续”。在性能场景中一定要做到的。因为生产环境没有不连续情况,并且在生产环境中,用户量肯定由少到多、有起伏变化。也只有这两个关键词能把场景的基调给定下来。


1.2.1 基准场景

对系统完全不了解时,先要清楚系统大概容量能力,从哪开始呢?基准场景。


如电商系统,测试11个业务。一上来就把这11个业务脚本做出来,上去压?肯定不行,因为还不知道每个业务能跑多大TPS,有无性能瓶颈。直接混合压,会导致多个性能问题一起暴露并相互影响,难以分析。


所以,先做单接口的基准场景。


先做“单接口的基准场景”,这的单接口在jmeter脚本中是否可理解为一个线程组下面只有一个HTTP请求?若是,那对于那种有上下关联参数的接口,个别入参只能使用一次的情况怎么解决?提前造足够的数据。


① 具体咋做?

拿几个用户测试登录接口的基本性能(这尝试过程本身不是基准场景):



57.png

可见1个压力线程大概产生20TPS。


单接口的容量达到多少才不影响混合的容量场景?

若这是单登录接口,须高过50TPS。而我们现在用的是8C 16G,根据CRUD测试经验,即使不走缓存,这样操作要达到500TPS没啥问题。


在一个线程能产生20 TPS前提下,先假设接口能达最大500 TPS都是线性的,就需:


线程数 = 500 T P S ÷ 20 T P S = 25 个线程 线程数 = 500 TPS \div 20 TPS = 25 个线程

线程数=500TPS÷20TPS=25个线程


因1个压力线程大概产生20 TPS,从TPS曲线看还是上升较快,所以考虑把Duration(场景的持续时间)放长,让压力不要增加太快,而在这缓慢增加过程中观察曲线变化,以判断后续动作及最大容量。我会这样来确定场景的加压过程。


56.png


在图中,我上到了30个线程,这里也可以不要高出那么多,只要高出25个线程就可以了。我把Ramp-up period设置为600秒,也就是20秒上一个线程,这样就会产生一个明显的连续递增的过程。


② 思路总结

先确定单线程运行时的TPS值

根据系统最大的预估容量,设置场景中的线程数、递增参数等。若你不会预估容量,可直接多加一些线程,然后在递增过程中查看曲线变化

确定正式基准场景的压力参数

当然,对于这个过程,也要在测试过程不断修正。


③ 基准场景的目的

获得单接口最大TPS:如果单接口最大TPS没有超过容量场景中的要求,那就必须要调优。如某容量场景的目标TPS 100,里面包含某单接口的调用,那这单接口的基准场景测试的TPS就不应低于100。


若超过了,是否就无需调优了呢?再看第二目的。


解决单接口基准场景中遇到的性能问题:做单接口测试时,碰到性能瓶颈一定要分析,这就涉及性能分析逻辑。


所以,性能分析基本分为两阶段:


第一阶段:硬件资源用完。基准场景中,要把CPU、内存、网络、IO等资源中的任一耗尽,因为此时易从全局监控的性能计数器看到现象,可以接着去跟踪分析

第二阶段:优化到最高TPS。基准场景中要把单接口TPS调到最高,以免成为容量场景中的瓶颈点

若第一阶段目标达不到,肯定要找瓶颈点:


若硬件资源已用完,TPS也满足容量场景的要求,从成本考虑,这项目无需再继续

若硬件资源用完,但TPS没满足容量场景的要求,须优化

执行一个单接口场景,将上面思路落地。


2 登录接口实战


按基准场景的设计步骤,先试运行接口的基准场景。


基准测试中,试运行只为看下基本的接口响应时间,并非为完成基准场景:


55.png


满目疮痍!虽场景执行时间不长,但10个线程上来就报错,响应时间、TPS也达到失望程度,仅12.5TPS,咋办啊?只能分析它!来看如何将性能分析思路落地。


你肯定好奇,报错是报啥错了呢?我认为应先跑下单接口,测试单接口的响应时间(虽然上10个线程也能暴露问题),但一看单接口响应时间就5s+,应该先解决这个问题,再上压力也不迟。


报错就是没断言到“成功”。解决的就是响应时间的问题呀。不解决问题响应时间怎么会下来呢。

2.1 问题现象

如图所示,现象不言而喻。


2.2 分析过程

按RESAR性能分析逻辑,针对响应时间长,先要做拆分时间。通过SkyWalking看时间浪费在哪:


54.png


一个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

4.png

用上面语句层层跟踪,最终到:

4.png



其他工具也可达类似效果,别迷恋工具。


既然这authenticate方法耗时比较长,就打开源码看这段:


3.png


Debug进去:


2.png


原来,这里是个加密算法BCrypt。


2.3 优化方案

Bcrypt加密时,每次HASH出的值不同,且特慢!用更快的加密方式或去掉这加密算法。


先去掉该加密算法,继续往下走。


2.4 优化效果


1.png

同样线程数,现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,再根据评估的单接口容量计算要多少线程,最后计算出的线程设置单接口的性能测试?


对压力工具这边的操作,是这样的。不过基准场景中,还要监控分析。

目录
相关文章
|
7天前
|
缓存 前端开发 JavaScript
利用代码分割优化前端性能:策略与实践
在现代Web开发中,代码分割是提升页面加载性能的有效手段。本文介绍代码分割的概念、重要性及其实现策略,包括动态导入、路由分割等方法,并探讨在React、Vue、Angular等前端框架中的具体应用。
|
4月前
|
SQL 安全 Java
探索软件测试的多维策略:从单元到集成,再到性能与安全
在软件开发生命周期中,测试是不可或缺的一环。本文将深入探讨软件测试的多维策略,从单元测试、集成测试到性能测试和安全测试等各个层面进行剖析。我们将通过具体的统计数据和案例分析,揭示不同测试策略的优势和应用场景。文章旨在为读者提供一个全面的测试框架,帮助他们构建更稳定、高效和安全的系统。
96 2
|
1月前
|
数据采集 自然语言处理 算法
|
3月前
|
测试技术 持续交付
探索式测试:一种高效且灵活的软件质量保证策略
在快速迭代和持续交付的软件开发环境中,传统的测试方法往往难以应对日益增长的测试需求。探索式测试作为一种灵活而高效的测试实践,强调测试人员的个人技能和经验,鼓励在测试过程中不断探索和学习。本文将介绍探索式测试的核心概念、实施步骤以及如何将其与传统测试方法相结合,以提升软件质量和测试效率。
|
4月前
|
存储 SQL 运维
MSSQL性能调优精要:索引深度优化、查询高效重构与并发精细控制
在MSSQL数据库的运维与优化领域,性能调优是一项复杂而细致的工作,直接关系到数据库的稳定性和响应速度
|
4月前
|
机器学习/深度学习 自然语言处理 数据挖掘
RouteLLM:高效LLM路由框架,可以动态选择优化成本与响应质量的平衡
新框架提出智能路由选择在强弱语言模型间,利用用户偏好的学习来预测强模型胜率,基于成本阈值做决策。在大规模LLMs部署中,该方法显著降低成本而不牺牲响应质量。研究显示,经过矩阵分解和BERT等技术训练的路由器在多个基准上提升性能,降低强模型调用,提高APGR。通过数据增强,如MMLU和GPT-4评审数据,路由器在GSM8K、MMLU等测试中展现出色的性能提升和成本效率。未来将测试更多模型组合以验证迁移学习能力。该框架为LLMs部署提供了成本-性能优化的解决方案。
141 2
|
6月前
|
监控 测试技术 持续交付
构建高效持续集成系统的策略与实践
【5月更文挑战第28天】 在快速迭代的软件开发过程中,持续集成(CI)系统是确保代码质量和加速交付的关键。本文将探讨构建一个高效、可靠的CI系统的关键策略,并通过实际案例分析如何实现这些策略。我们将讨论自动化测试、容器化部署、监控和日志记录等主题,以及它们如何共同作用以提升开发流程的效率和稳定性。通过实施这些策略,团队可以显著减少集成问题,并缩短从开发到部署的时间。
94 2
|
6月前
|
机器学习/深度学习 数据采集 算法
构建高效机器学习模型的策略与优化路径
【5月更文挑战第28天】 在数据驱动的时代,机器学习模型的效能已成为衡量技术创新的重要指标。本文旨在探讨如何通过策略性的方法构建高效的机器学习模型,并详细阐述优化过程的关键步骤。文章首先对当前机器学习领域面临的挑战进行分析,随后提出一系列切实可行的模型构建和优化策略,包括数据预处理的重要性、特征工程的核心地位、算法选择的多样性以及超参数调优的必要性。通过对这些策略的深入讨论,本文为读者提供了一套系统的方法论,以期达到提高模型性能和泛化能力的目的。
|
6月前
|
存储 缓存 安全
【C/C++ 项目优化实战】 分享几种基础且高效的策略优化和提升代码性能
【C/C++ 项目优化实战】 分享几种基础且高效的策略优化和提升代码性能
344 0
|
算法 调度 决策智能
贪心算法:简单而高效的优化策略
贪心算法:简单而高效的优化策略
225 1
下一篇
无影云桌面