学习链接:《性能学习实战30讲》
授课人:高楼
课程从三个部分进行阐述:
- 第一个模块是性能测试基础篇。在这个模块里澄清一些性能测试的基础概念,讲解一些关键部分。但并不是对概念的简单描述,而是根据实际项目,讲真正具有指导价值的性能测试概念是什么,并解析这些概念在实际操作中的指导性作用。
- 在第二个模块中,通过性能测试工具的实际操作实例,对应性能测试的前后逻辑关系。在这一部分中,重点讲解为什么要使用某些工具的某些功能,以便确保工具的使用及结果是为性能测试需求指标和性能分析报告而服务的,而不是浮于表面的“炫技”。
- 在第三个模块中,通过操作系统、应用服务器、数据库、缓存服务器、Java、C++ 等监控工具的使用和分析方法,阐述它们产生的数据在性能分析过程中该如何判断,为测试报告及性能分析提供有效的历史数据。
目标:让性能变得有价值
在性能测试分析优化之前,如果 TPS 是 100,你做完了之后 TPS 是 10000,这就是价值。
在性能测试分析优化之前,如果响应时间是 0.1ms,你做完了之后是 0.01ms,这就是有价值。
在性能测试分析优化之前,如果 CPU 使用率是 100%,你做完了之后是 50%,这就是有价值。
1、性能测试的概念是什么?
一图看完本节内容
1)要有指标
往往指标都是一句话:把系统压死为止。这也算指标。
- 时间指标
- 容量指标
- 资源利用率指标
2)要模型
模型:参考生产环境的数据,进行统计出来一个各个业务的并发量,根据并发量确定业务的权重,做出来一个业务权重模型。
灵魂问题:性能流量直接从生产上导的话,是不是就可以不用性能测试人员了?性能测试人员就要被淘汰了?
3)要有方案
方案内容:
- 测试环境
- 测试数据
- 测试模型
- 性能指标
- 压力策略
- 准入准出标准
- 进度风险
使用项目管理工具(比如用 Project 或 OmniPlan 之类的工具。)制定测试计划,不仅可以细分条目,还能跟踪各个工作的动态进度,可以设置前后依赖关系,填入资源和成本以便计算项目偏差。
4)要有监控
- 要有分层分段能力
- 要有全局监控、定向监控能力
5)要有预定条件
测试前需要确认好以下内容
- 硬件环境
- 测试数据
- 测试执行策略
- 压力补偿
6)要有场景
场景来源于英文的 scenario,对性能场景中的“场景”比较正宗的描述是:在既定的环境(包括动态扩展等策略)、既定的数据(包括场景执行中的数据变化)、既定的执行策略、既定的监控之下,执行性能脚本,同时观察系统各层级的性能状态参数变化,并实时判断分析场景是否符合预期。
场景的常见分类
- 基准性能场景:这里要做的是单交易的容量,为混合容量做准备(不要跟我说上几个线程跑三五遍脚本叫基准测试,在我看来,那只是场景执行之前的预执行,用来确定有没有基本的脚本和场景设计问题,不能称之为一个分类)。
- 容量性能场景:这一环节必然是最核心的性能执行部分。根据业务复杂度的不同,这部分的场景会设计出很多个,在概念部分就不细展开了,会在后面的文章中详细说明。
- 稳定性性能场景:稳定性测试必然是性能场景的一个分类。只是现在在实际的项目中,稳定性测试基本没和生产一致过。在稳定性测试中,显然最核心的元素是时间(业务模型已经在容量场景中确定了),而时间的设置应该来自于运维周期,而不是来自于老板、产品和架构等这些人的心理安全感。
- 异常性能场景:要做异常性能场景,前提就是要有压力。在压力流量之下,模拟异常。这个异常的定义是很宽泛的
7)要有分析调优
要不要对项目进行调优,先需要理解性能项目分类,也就是对团队人员的定位。
- 新系统性能测试类:这样的项目一般都会要求测试出系统的最大容量,不然上线心里没底。旧系统新版本性能测试类:这样的项目一般都是和旧版本对比,只要性能不下降就可以根据历史数据推算容量,对调优要求一般都不大。
- 新系统性能测试优化类:这类的系统不仅要测试出最大容量,还要求调优到最好。对性能团队的职责定位有如下几种。
- 性能验证:针对给定的指标,只做性能验证。第三方测试机构基本上都是这样做的。
- 性能测试:针对给定的系统,做全面的性能测试,可以得到系统最大容量,但不涉及到调优。
- 性能测试 + 分析调优:针对给定的系统,做全面的性能测试,同时将系统调优到最优状态。
8)要有性能结果报告
- 场景结果整理
- 监控结果整理
- 性能整体分析
- 性能结论
- 优化建议
- 运维建议
2、TPS和响应时间之间是什么关系?
- 三条曲线:吞吐量的曲线(紫色)、利用率(绿色)、响应时间曲线(深蓝色)。
- 三个区域:轻负载区(Light Load)、重负载区(Heavy Load)、塌陷区(Buckle Zone)。
- 两个点:最优并发用户数(The Optimum Number of Concurrent Users)、最大并发用户数(The Maximum Number of Concurrent Users)。
- 三个状态描述:资源饱和(Resource Saturated)、吞吐下降(Throughput Falling)、用户受影响(End Users Effected)。
上图中蓝线表示 TPS,黄色表示响应时间。
在 TPS 增加的过程中,响应时间一开始会处在较低的状态,也就是在 A 点之前。接着响应时间开始有些增加,直到业务可以承受的时间点 B,这时 TPS 仍然有增长的空间。再接着增加压力,达到 C 点时,达到最大 TPS。我们再接着增加压力,响应时间接着增加,但 TPS 会有下降(请注意,这里并不是必然的,有些系统在队列上处理得很好,会保持稳定的 TPS,然后多出来的请求都被友好拒绝)。
3、性能综述:怎么理解TPS、QPS、RT、吞吐量这些性能指标?
1)理解业务指标和性能指标之间的关系
2)业内常用性能指标表示法
3)对这些性能指标都有哪些误解
- QPS 一开始是用来描述 MySQL 中 SQL 每秒执行数 Query Per Second,所有的 SQL 都被称为 Query。后来,由于一些文章的转来转去,QPS 被慢慢地移到了压力工具中,用来描述吞吐量,于是这里就有些误解,QPS 和 TPS 到底是什么关系呢?
- RPS 指的是每秒请求数。这个概念字面意思倒是容易理解,但是有个容易误解的地方就是,它指的到底是哪个层面的 Request?如果说 HTTP Request,那么和 Hits Per Second 又有什么关系呢?
- HPS,这也是个在字面意思上容易理解的概念。只是 Hit 是什么?有人将它和 HTTP Request 等价,有人将它和用户点击次数等价。
4)指标的正确的理解
TPS 应该如何定义?
通常情况下,我们会根据场景的目的来定义 TPS 的粒度。
如果是接口层性能测试,T 可以直接定义为接口级;
如果业务级性能测试,T 可以直接定义为每个业务步骤和完整的业务流。
如果我们要单独测试接口 1、2、3,那 T 就是接口级的;如果我们要从用户的角度来下一个订单,那 1、2、3 应该在一个 T 中,这就是业务级的了。
所以,性能中 TPS 中 T 的定义取决于场景的目标和 T 的作用。一般我们都会这样来定事务。
- 接口级脚本: - ——事务 start(接口 1)- 接口 1 脚本- ——事务 end(接口 1)- ——事务 start(接口 2)- 接口 2 脚本- ——事务 end(接口 2)- ——事务 start(接口 3)- 接口 3 脚本- ——事务 end(接口 3)
- 业务级接口层脚本(就是用接口拼接出一个完整的业务流): - ——事务 start(业务 A)- 接口 1 脚本 - 接口 2(同步调用)- 接口 1 脚本 - 接口 3(异步调用)- ——事务 end(业务 A)
- 用户级脚本 - ——事务 start(业务 A)- 点击 0 - 接口 1 脚本 - 接口 2(同步调用)- 点击 0 - 接口 1 脚本 - 接口 3(异步调用)- ——事务 end(业务 A)
你要创建什么级别的事务,完全取决于测试的目的是什么。
因此,TPS就是每秒事务数。它可以反应出一个系统的处理能力。
QPS应该如何定义?
它描述的是数据库中的 Query Per Second,从上面的示意图中来看,其实描述的是服务后面接的数据库中 SQL 的每秒执行条数。如果描述的是前端的每秒查询数,那就不包括插入、更新、删除操作了。显然这样的指标用来描述系统整体的性能是不够全面的。所以不建议用 QPS 来描述系统整体的性能,以免产生误解。
RPS(Request per second)如何定义?
每秒请求数。
如果一个用户点击了一次,发出来 3 个 HTTP Request,调用了 2 次订单服务,调用了 2 次库存服务,调用了 1 次积分服务,那么这个 Request 该如何计算?如果你是算 GDP 的专家,我觉得可能会是:3+2+2+1=8(次)。而在具体的项目中,我们会单独描述每个服务,以便做性能统计。如果要描述整体,最多算是有 3 个 RPS。如果从 HTTP 协议的角度去理解,那么 HTTP Request 算是一个比较准确的描述了,但它本身的定义并没有包含业务。如果赋予它业务的含义,那么用它来描述性能也是可以的。
HPS(Hits Per Second)如何定义?
每秒点击数。Hit 一般在性能测试中,都用来描述 HTTP Request。但是,也有一些人用它描述真正的客户在界面上的点击次数。
CPS/CPM:Calls Per Second/ Calls Per Minutes
每秒 / 每分钟调用次数。这个描述在接口级是经常用到的,比如说上面的订单服务。显然一次客户界面上的点击调用两次。这个比较容易理解。但是,在操作系统级,我们也经常会听到系统调用用 call 来形容,比如说用 strace 时,你就会看见 Calls 这样的列名。
响应时间 RT
RT = T2-T1。计算方式非常直接简单。但是,我们要知道,这个时间包括了后面一连串的链路。
如何排查rt较高的问题?
在所有服务的进出口上都做记录,然后计算结果就行了。在做网关、总线这样的系统时,基本上都会考虑这个功能。
而现在,随着技术的发展,链路监控工具和一些 Metrics 的使用,让这个需求变得简单了不少。比如说这样的展示:
5)线程数和用户数与 TPS(压力工具中的)
上面这张示意图中,其实压力工具是 4 个并发线程,由于每个线程都可以在一秒内完成 4 个事务,所以总的 TPS 是 16。这非常容易理解吧。而在大部分非技术人的脑子里,这样的场景就是并发数是 4,而不是 16。
那么用户数怎么来定义呢?涉及到用户就会比较麻烦一点。因为用户有了业务含义,所以有些人认为一个系统如果有 1 万个用户在线,那就应该测试 1 万的并发线程,这种逻辑实在是不技术。通常,我们会对在线的用户做并发度的分析,在很多业务中,并发度都会低于 5%,甚至低于 1%。
拿 5% 来计算,就是 10000 用户 x5%=500(用户级 TPS),注意哦,这里是 TPS,而不是并发线程数。如果这时响应时间是 100ms,那显然并发线程数是 500TPS/(1000ms/100ms)=50(并发线程)。
通过这样简单的计算逻辑,我们就可以看出来用户数、线程数和 TPS 之间的关系了。
响应时间肯定不会一直都是 100ms,因此这个关系是一个动态的趋势问题
6)28 原则是什么?
作者否定:有些文章中写性能测试要按 28 原则来计算并发用户数。大概的意思就是,如果一天有 1000 万的用户在使用,系统如果开 10 个小时的话,在计算并发用户数的时候,就用 2 小时来计算,即 1000 万用户在 2 小时内完成业务。
业务模型应该如何得到呢?这里有两种方式是比较合理的:
- 根据生产环境的统计信息做业务比例的统计,然后设定到压力工具中。有很多不能在线上直接做压力测试的系统,都通过这种方式获取业务模型。
- 直接在生产环境中做流量复制的方式或压力工具直接对生产环境发起压力的方式做压力测试。这种方式被很多人称为全链路压测。其实在生产中做压力测试的方式,最重要的工作不是技术,而是组织协调能力。
响应时间如何设计比较合理呢?这里有两种思路推荐
- 同行业的对比数据。
- 找到使用系统的样本用户(越多越好),对他们做统计,将结果拿出来,就是最有效的响应时间的制定标准。
7)性能指标的计算方式
4、JMeter和LoadRunner:要知道工具仅仅只是工具
常用工具进行对比
这是全球范围内 5 年 JMeter 和 LoadRunner 热度(红色线是 LoadRunner,蓝色线是 JMeter):
中国范围近 5 年 JMeter 和 LoadRunner 热度:
性能工程师有三大学习阶段
- 性能工具学习期
- 性能场景学习期
- 性能分析学习期
1)性能工具学习期 - 初级性能工程师
JMeter、LoadRunner 的基本功能学会,做两件事,做脚本和发压力
2)性能场景学习期 - 中级性能工程师
压力策略,直白一点说,就是根据业务场景,调整工具中的参数
3)性能分析学习期 - 高级性能工程师
性能团队的三大发展阶段
1)性能团队初建
- 编写脚本,执行场景
- 拿出性能测试结果
- 根据TPS和响应时间,做版本基线进行对比,出一个数据罗列式的性能测试报告
2)性能团队初成熟
- 做好准入准出
- 制定性能标准
- 在发布流程做卡点
3)性能团队已成熟
- 通过性能测试和分析优化后,依据数据指标,确认性能提升了多少
- 通过你的测试和分析优化之后,节省了多少成本?如:节省了多少台机器
- 有完整的数据监控平台
如何选择适合自己的工具?
四问:
- 工具能做什么
- 工具不能做什么?
- 我们用工具的目标是什么?
- 当工具达不到目标时,我们怎么办?
- 使用第三方的压测服务:如果已经买了人家的云服务器,可以直接顺带购买,并且压测场景并不算经常用可以选择
- 长期使用,压力机不可控:自己开发
- 政府和事业单位:直接购买第三方,可以随时叫过来做技术支持
5、并发用户数应该怎么计算?
1)什么是并发
绝对并发:CPU个数,就是绝对并发
相对并发:1s内的任务个数
我们假设上图中的这些小人是严格按照这个逻辑到达系统的,那显然,系统的绝对并发用户数是 4。如果描述 1 秒内的并发用户数,那就是 16(1s钟每一个用户迭代了4次)。
在实际的系统中,用户通常是这样分配的:
并发数是 16TPS,就是 1 秒内整个系统处理了 16 个事务。这样描述就够了,不需要纠结。
2)在线用户数、并发用户数怎么计算?
如上图所示,总共有 32 个用户进入了系统,但是绿色的用户并没有任何动作,那么显然,在线用户数是 32 个,并发用户数是 16 个,这时的并发度就是 50%。并发(1s为单位)
实际系统中
为了能 hold 住更多的用户,我们通常都会把一些数据放到 Redis 这样的缓存服务器中。所以在线用户数怎么算呢,如果仅从上面这种简单的图来看的话,其实就是缓存服务器能有多大,能 hold 住多少用户需要的数据。
最多再加上在超时路上的用户数。如下所示:
所以我们要是想知道在线的最大的用户数是多少,对于一个设计逻辑清晰的系统来说,不用测试就可以知道,直接拿缓存的内存来算就可以了。
因此。
在线用户数:假设一个用户进入系统之后,需要用 10k 内存来维护一个用户的信息,那么 10G 的内存就能 hold 住 1,048,576 个用户的数据,这就是最大在线用户数了。在实际的项目中,我们还会将超时放在一起来考虑。
什么是并发度:在线用户数 / 并发用户数
我们经常使用性能测试工具,设置线程的等待时间(Sleep时间)来保持用户和系统之间的session不断开,但实际上的并发量特别低
上图是几个指标之间的计算关系
- 在线用户数10000,并发度为1%时,也就是1s钟内并发用户数为100
- 如果压力机上边,每个线程是20TPS,那么我们只需要有5个线程
- 平均响应时间是怎么计算的呢?1s钟内有1000ms / 20TPS = 50ms
- 因此我们的服务需要1s内处理这100个并发用户的任务,因此,我们的Server 为100TPS,如果有两个线程,那么一个线程就是50 TPS
我们在整个性能测试中,最需要关注的指标是:服务端的处理能力。
举例:
JMeter(1 个线程) - Nginx - Tomcat - MySQL
Jmeter的处理结果:
summary + 5922 in 00:00:30 = 197.4/s Avg: 4 Min: 0 Max: 26 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 35463 in 00:03:05 = 192.0/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
summary + 5922 in 00:00:30 = 197.5/s Avg: 4 Min: 0 Max: 24 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 41385 in 00:03:35 = 192.8/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
summary + 5808 in 00:00:30 = 193.6/s Avg: 5 Min: 0 Max: 25 Err: 0 (0.00%) Active: 1 Started: 1 Finished: 0
summary = 47193 in 00:04:05 = 192.9/s Avg: 5 Min: 0 Max: 147 Err: 0 (0.00%)
我们可以看到,JMeter 的平均响应时间基本都在 5ms,因为只有一个压力机线程,所以它的 TPS 应该接近 1000ms / 5ms=200TPS。
问:为什么有的数据行会少一点?
因为这里算的是平均数,并且这个数据是 30s 刷新一次,用 30 秒的时间内完成的事务数除以 30s 得到的,但是如果事务还没有完成,就不会计算在内了;同时,如果在这段时间内有一两个时间长的事务,也会拉低 TPS。
那么对于服务端呢,我们来看看服务端线程的工作情况。
可以看到在服务端,我开了 5 个线程,但是服务端并没有一直干活,只有一个在干活的,其他的都处于空闲状态。
这是一种很合理的状态。但是需要注意的是,这种合理的状态并不一定是对的性能状态。
- 并发用户数(TPS)是 193.6TPS。如果并发度为 5%,在线用户数就是 193.6 / 5%=3872。
- 响应时间是 5ms。
- 压力机并发线程数是 1。这一条,我们通常也不对非专业人士描述,只要性能测试工程师自己知道就可以了。
错误的压力测试操作:
压力工具中要使用 4000 个线程,结果研发为了测试4000线程,给服务端的 Tomcat 上也配置了 4000 个线程,结果 Tomcat 一启动,稍微有点访问,CS (Context Switch)就特别高,结果导致请求没处理多少,自己倒浪费了不少 CPU。
需要服务端设置回正常的
6、性能测试分析思路
性能测试分析的能力阶梯视图
- 工具操作:包括压力工具、监控工具、剖析工具、调试工具。
- 数值理解:包括上面工具中所有输出的数据。
- 趋势分析、相关性分析、证据链分析:就是理解了工具产生的数值之后,还要把它们的逻辑关系想明白。这才是性能测试分析中最重要的一环。
- 最后才是调优:有了第 3 步之后,调优的方案策略就有很多种了,具体选择取决于调优成本和产生的效果。
性能分析思路大纲:
- 瓶颈的精准判断;
- 线程递增的策略;
- 性能衰减的过程;
- 响应时间的拆分;
- 构建分析决策树;
- 场景的比对。
1)瓶颈的精准判断
TPS 曲线
这样的趋势图中,我们是看不到明确的拐点的。
但是我们能做的清晰的判断就是:有瓶颈!
所以对 TPS 曲线来说,它可以明确告诉我们的就是:
- 有没有瓶颈:其实准确说所有的系统都有性能瓶颈,只看我们在哪个量级在做性能测试了。
- 瓶颈和压力有没有关系:TPS 随着压力的变化而变化,那就是有关系。不管压力增不增加,TPS 都会出现曲线趋势问题,那就是无关。
这时你可能会问,为什么不看响应时间就武断地下此结论呢?其实响应时间是用来判断业务有多快的,而 TPS 才是用来判断容量有多大的。
响应时间的曲线
对应的线程图
多明显的问题,随着线程的增多,响应时间也在增加,是吧。再来看它们对应的 TPS 图:
到第 40 个线程时,TPS 基本上达到上限,为 2500 左右。响应时间随着线程数的增加而增加了,系统的瓶颈显而易见地出现了。
但是,如果只让你看 TPS 曲线,你是不是也会有同样的判断?那就是:有瓶颈!并且和压力有关?所以说,其实 TPS 就可以告诉我们系统有没有瓶颈了,而响应时间是用来判断业务有多快的。
2)线程递增的策略
我们来看两个场景的执行对比。
场景 1 的线程图:
场景 1 的 TPS 图:
场景 1 的响应时间图:
场景 2 的线程图:
场景 2 的 TPS 图:
场景 2 的响应时间图:
这两个场景的比对如下:
TPS 都是达到 400,但两个场景中线程递增的策略不同,产生的响应时间完全不同。虽然都没有报错,但是第一种场景是完全不符合真实的业务场景的。
场景 2 使用了递增的策略,在每个阶梯递增的过程中,出现了抖动,这就明显是系统设置的不合理导致的。设置不合理,有两种可能性:
- 资源的动态分配不合理,像后端线程池、内存、缓存等等;
- 数据没有预热。
那么,对于场景中线程(有些工具中叫虚拟用户)递增的策略,我们要做到以下几点:
- 场景中的线程递增一定是连续的,并且在递增的过程中也是有梯度的。
- 场景中的线程递增一定要和 TPS 的递增有比例关系,而不是突然达到最上限。后面在场景的篇幅中我们会再说它们之间的比例关系。
上面两点针对的是常规的性能场景。对于秒杀类的场景,我们前期一定是做好了系统预热的工作的,在预热之后,线程突增产生的压力,也是在可处理范围的。这时,我们可以设计线程突增的场景来看系统瞬间的处理能力。如果不能模拟出秒杀的陡增,就是不合理的场景。
3)性能衰减的过程
有了瓶颈的判断能力,也有了线程递增的意识,那么下面在场景执行中,我们就要有判断性能衰减的能力了吧。
我们先看一个压力过程中产生的结果图。
在递增的压力过程中,随着用户数的增加。我们可以做几次计算。
- 第一次计算,在线程达到 24 时,TPS 为 1810.6,也就是每线程每秒发出 75.44 个请求。
- 第二次计算,在线程达到 72 时,TPS 为 4375.1,也就是每线程每秒发出 60.77 个请求。
- 第三次计算,在线程达到 137 时,TPS 为 5034,也就是每线程每秒发出 36.74 个请求。
通过这三次计算,我们是不是可以看到,每线程每秒发出的请求数在变少,但是整体 TPS 是在增加的。
我们有很多做性能测试的人,基本上,只看 TPS 和响应时间的时候,在上面这个示例中,肯定会一直往上加用户。虽然响应时间在增加,但是增加得也不多嘛。
但实际上,通过我们的计算可以知道,性能是在不断地衰减的。我们来看一张统计图:
通过红线的大致比对可以知道,当每线程每秒的请求数降到 55 左右的时候,TPS 就达到上限了,大概在 5000 左右,再接着往上增加线程已经没有用了,响应时间开始往上增加了。
这就是性能衰减的过程(题外话,在上图中,其实还有一个问题,就是在红线前面,性能在上升的过程中有几次抖动,这个抖动到后面变大了,也变频繁了,如果这是必然出现的抖动,那也是配置问题,希望你注意到这一点)。
为什么需要细致描述性能衰减过程?
只要每线程每秒的 TPS 开始变少,就意味着性能瓶颈已经出现了。但是瓶颈出现之后,并不是说服务器的处理能力(这里我们用 TPS 来描述)会下降,应该说 TPS 仍然会上升,在性能不断衰减的过程中,TPS 就会达到上限。
也就是说:性能瓶颈其实在最大 TPS 之前早就已经出现了。
那么我们是不是应该在性能衰减到最大 TPS 时就停止场景呢?
这个不一定的哦。因为停不停场景,取决于我们的场景目标,如果我们只是为了得到最大 TPS,那确实可以停止场景了。但是,如果我们要扩大化性能瓶颈,也就是说为了让瓶颈更为明显,就完全不需要停止场景,只要不报错,就接着往上压,一直压到我们要说的下一个话题——响应时间变长,需要拆分。
4)响应时间的拆分
如果我们要分析压力工具中的响应时间,拆分的逻辑就是上面这个示意图。
但是在真实的场景中,基本上不是这样的。如果是内网,那基本上都是连在一个交换机上,所以通常是这样的:
在这样的拓扑中,我们仍然可以拆出来 t1 到 t8 的时间。只是实际动手的时候,思路一定要清晰,时间拆分是从哪里到哪里,要画出来,不能混乱。
我们有很多手段可以进行时间的拆分,当然要看我们的应用支持哪一种。
如果我们是这样的架构,拆分时间应该是比较清楚的。
首先我们需要查看 Nginx 上的时间。日志里就可以通过配置
requesttimeupstream_response_time
得到日志如下信息:
14.131.17.129 - - [09/Dec/2019:08:08:09 +0000]"GET / HTTP/1.1" 200 25317 0.028 0.028
最后两列中,前面是请求时间的 28ms,后面是后端响应时间的 28ms。
同时,我们再到 Tomcat 上去看时间。
172.18.0.1 - - [09/Dec/2019:08:08:09 +0000]"GET / HTTP/1.1" 200 25317 28 27 http-nio-8080-exec-1
请求时间消耗了 28ms,响应时间消耗了 27ms。
再来看一下前端的时间消耗。
从这里可以看到,从发出请求到接收到第一个字节,即 TTFB 是 55.01ms,内容下载用了 11.75ms。从这就可以看得出 Nginx 基本上没消耗时间,因为它和 Tomcat 上的请求响应时间非常接近。
那么网络上的消耗时间怎么样呢?我看到有很多人用 TTFB 来描述网络的时间。先来说明一下,TTFB 中显然包括了后端一系列处理和网络传输的时间。如下图所示。
下面的紫色点是指要接收的内容。上面的红色线就是 TTFB。
Tomcat 上基本上是消耗了处理的所有时间,当然这中间也包括了 MySQL 花费的时间。而前端看到的其他时间就消耗在了网络中。
主要说明了响应时间怎么一步步拆。当然,如果你是下面这种情况的话,再一个个拆就比较辛苦了,需要换另一种方式。
你肯定想知道每个系统消耗了多长时间,那么我们就需要链路监控工具来拆分时间了。比如像这样来拆分:
从 User 开始,每个服务之间的调用时间,都需要看看时间消耗的监控。这就是时间拆分的一种方式。
其实不管我们用什么样的工具来监控,最终我们想得到的无非是每个环节消耗了多长时间。用日志也好,用链路监控工具也好,甚至抓包都可以。
5)构建分析决策树
当我们拆分到了某个环节之后,就有了下一步的动作:构建分析决策树。
分析决策树,对性能测试分析人员实在是太重要了,是性能分析中不可或缺的一环。它是对架构的梳理,是对系统的梳理,是对问题的梳理,是对查找证据链过程的梳理,是对分析思路的梳理。它起的是纵观全局,高屋建瓴的指导作用。
通过上面的几个步骤,我们就会知道时间消耗在了哪个节点上。那么之后呢?又当如何?
总要找到根本的原因才可以吧,我画了如下的分析决策图:
从压力工具中,只需要知道 TPS、响应时间和错误率三条曲线,就可以明确判断瓶颈是否存在。再通过分段分层策略,结合监控平台、日志平台,或者其他的实时分析平台,知道架构中的哪个环节有问题,然后再根据更细化的架构图一一拆解下去。
以数据库分析和操作系统分析举一下例子。
首先我们看一下数据库分析决策树。
比如针对 RDBMS 中的 MySQL,我们就可以画一个如下的决策树:
MySQL 中的索引统计信息有配置值,有状态值。我们要根据具体的结果来判断是否需要增加
key_buffer_size
值的大小。比如这种就无所谓了。
Buffer used 3.00k of 8.00M %Used: 0.0004
从上面的数据可以看到,
key buffer size
就用到了 4%,显然不用增加。
再比如,我们看到这样的数据:
__Tables_______________________
Open 2000 of 2000 %Cache: 100.00
Opened 15.99M 4.1/s
这就明显有问题了。配置值为 2000 的
Open Table Cache
,已经被占满了。显然这里需要分析。但是,看到状态值达到配置值并不意味着我们需要赶紧加大配置值,而是要分析是否合理,再做相应的处理。比如说上面这个,
Table
确实打开得多,但是如果我们再对应看下这一条。
Slow 2 s 6.21M 1.6/s
你是不是觉得应该先去处理慢 SQL 的问题了?
关于数据库的我们就不举更多的例子了。在这里只是为了告诉你,在分析决策树的创建过程中,有非常多的相互依赖关系。
再来看一下操作系统分析决策树,我在这里需要强调一下,操作系统的分析决策树,不可以绕过。
基于此决策树,每个人都可以做到对操作系统中性能问题的证据链查找。
“CPU 使用率在 TPS 上升的过程中,从 10% 增加到 95%,超过了预期值。” “内存使用率达到 99%,所以是瓶颈点。” “I/O 使用率达到 100%。” 等等。
像这样的描述,在作者的性能团队中,一定会被骂回去重写。我要这些描述有什么用?我要的是为什么达到了这样的值,原因在哪?怎么解决?
举个例子:
中断能占 40%,sy CPU 也能占 40%。这系统还用干业务的事吗?全干自己的事去了,可见操作系统有问题!你是不是要做这个判断了?
而实际情况是,这个主机上只有一个网卡队列,而请求量又比较大。
所以要解决的是网卡队列的问题,至于怎么解决,那手段就多了。可以换个服务器,可以多加几个队列,可以多接几个节点…
以上只是给出几个性能分析过程中常见的决策树示例。在后续的分析过程实例中,我们将秉承着这种分析思路,一步步地走到瓶颈的面前。
6)场景的对比
其实简单来说,就一句话:当你觉得系统中哪个环节不行的时候, 又没能力分析它,你可以直接做该环节的增加。
举例,有一系统架构如下
可以得到这样的结果:
从 TPS 曲线中,我们可以明显看到系统是有瓶颈的,但是并不知道在哪里。鉴于系统架构如此简单,我们索性直接在某环节上加上一台服务器,变成这样:
然后得到如下数据:
哟,没好使!怎么办?再接着加其他节点,我加了更多的 JMeter 机器。
再来看下结果:
真巧,TPS 增加了!
这就是我说的场景比对。
当我们不知道系统中哪个环节存在性能瓶颈时,对架构并不复杂的系统来说,可以使用这样的手段,来做替换法,以快速定位问题。
版权归原作者 李易安QSR 所有, 如有侵权,请联系我们删除。