学习链接:《性能学习实战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 小时内完成业务。

业务模型应该如何得到呢?这里有两种方式是比较合理的:

  1. 根据生产环境的统计信息做业务比例的统计,然后设定到压力工具中。有很多不能在线上直接做压力测试的系统,都通过这种方式获取业务模型。
  2. 直接在生产环境中做流量复制的方式或压力工具直接对生产环境发起压力的方式做压力测试。这种方式被很多人称为全链路压测。其实在生产中做压力测试的方式,最重要的工作不是技术,而是组织协调能力。

响应时间如何设计比较合理呢?这里有两种思路推荐

  1. 同行业的对比数据。
  2. 找到使用系统的样本用户(越多越好),对他们做统计,将结果拿出来,就是最有效的响应时间的制定标准。

7)性能指标的计算方式

【性能学习】性能测试基础-编程知识网

【性能学习】性能测试基础-编程知识网

4、JMeter和LoadRunner:要知道工具仅仅只是工具

【性能学习】性能测试基础-编程知识网
常用工具进行对比
【性能学习】性能测试基础-编程知识网
这是全球范围内 5 年 JMeter 和 LoadRunner 热度(红色线是 LoadRunner,蓝色线是 JMeter):
【性能学习】性能测试基础-编程知识网
中国范围近 5 年 JMeter 和 LoadRunner 热度:
【性能学习】性能测试基础-编程知识网

性能工程师有三大学习阶段

  • 性能工具学习期
  • 性能场景学习期
  • 性能分析学习期

1)性能工具学习期 – 初级性能工程师

JMeter、LoadRunner 的基本功能学会,做两件事,做脚本和发压力

2)性能场景学习期 – 中级性能工程师

压力策略,直白一点说,就是根据业务场景,调整工具中的参数

3)性能分析学习期 – 高级性能工程师


性能团队的三大发展阶段

1)性能团队初建

  • 编写脚本,执行场景
  • 拿出性能测试结果
  • 根据TPS和响应时间,做版本基线进行对比,出一个数据罗列式的性能测试报告

2)性能团队初成熟

  • 做好准入准出
  • 制定性能标准
  • 在发布流程做卡点

3)性能团队已成熟

  • 通过性能测试和分析优化后,依据数据指标,确认性能提升了多少
  • 通过你的测试和分析优化之后,节省了多少成本?如:节省了多少台机器
  • 有完整的数据监控平台

如何选择适合自己的工具?

四问:

  1. 工具能做什么
  2. 工具不能做什么?
  3. 我们用工具的目标是什么?
  4. 当工具达不到目标时,我们怎么办?
  • 使用第三方的压测服务:如果已经买了人家的云服务器,可以直接顺带购买,并且压测场景并不算经常用可以选择
  • 长期使用,压力机不可控:自己开发
  • 政府和事业单位:直接购买第三方,可以随时叫过来做技术支持

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不断开,但实际上的并发量特别低
【性能学习】性能测试基础-编程知识网

上图是几个指标之间的计算关系

  1. 在线用户数10000,并发度为1%时,也就是1s钟内并发用户数为100
  2. 如果压力机上边,每个线程是20TPS,那么我们只需要有5个线程
  3. 平均响应时间是怎么计算的呢?1s钟内有1000ms / 20TPS = 50ms
  4. 因此我们的服务需要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 个线程,但是服务端并没有一直干活,只有一个在干活的,其他的都处于空闲状态。

这是一种很合理的状态。但是需要注意的是,这种合理的状态并不一定是对的性能状态。

  1. 并发用户数(TPS)是 193.6TPS。如果并发度为 5%,在线用户数就是 193.6 / 5%=3872。
  2. 响应时间是 5ms。
  3. 压力机并发线程数是 1。这一条,我们通常也不对非专业人士描述,只要性能测试工程师自己知道就可以了。

错误的压力测试操作:

压力工具中要使用 4000 个线程,结果研发为了测试4000线程,给服务端的 Tomcat 上也配置了 4000 个线程,结果 Tomcat 一启动,稍微有点访问,CS (Context Switch)就特别高,结果导致请求没处理多少,自己倒浪费了不少 CPU。
需要服务端设置回正常的

6、性能测试分析思路

性能测试分析的能力阶梯视图
【性能学习】性能测试基础-编程知识网

  1. 工具操作:包括压力工具、监控工具、剖析工具、调试工具。
  2. 数值理解:包括上面工具中所有输出的数据。
  3. 趋势分析、相关性分析、证据链分析:就是理解了工具产生的数值之后,还要把它们的逻辑关系想明白。这才是性能测试分析中最重要的一环。
  4. 最后才是调优:有了第 3 步之后,调优的方案策略就有很多种了,具体选择取决于调优成本和产生的效果。

性能分析思路大纲:

  • 瓶颈的精准判断;
  • 线程递增的策略;
  • 性能衰减的过程;
  • 响应时间的拆分;
  • 构建分析决策树;
  • 场景的比对。

1)瓶颈的精准判断

TPS 曲线

【性能学习】性能测试基础-编程知识网
这样的趋势图中,我们是看不到明确的拐点的。
但是我们能做的清晰的判断就是:有瓶颈!

所以对 TPS 曲线来说,它可以明确告诉我们的就是:

  1. 有没有瓶颈:其实准确说所有的系统都有性能瓶颈,只看我们在哪个量级在做性能测试了。
  2. 瓶颈和压力有没有关系:TPS 随着压力的变化而变化,那就是有关系。不管压力增不增加,TPS 都会出现曲线趋势问题,那就是无关。

这时你可能会问,为什么不看响应时间就武断地下此结论呢?其实响应时间是用来判断业务有多快的,而 TPS 才是用来判断容量有多大的。

响应时间的曲线

【性能学习】性能测试基础-编程知识网

对应的线程图
【性能学习】性能测试基础-编程知识网

多明显的问题,随着线程的增多,响应时间也在增加,是吧。再来看它们对应的 TPS 图:
【性能学习】性能测试基础-编程知识网
到第 40 个线程时,TPS 基本上达到上限,为 2500 左右。响应时间随着线程数的增加而增加了,系统的瓶颈显而易见地出现了。

但是,如果只让你看 TPS 曲线,你是不是也会有同样的判断?那就是:有瓶颈!并且和压力有关?所以说,其实 TPS 就可以告诉我们系统有没有瓶颈了,而响应时间是用来判断业务有多快的。

2)线程递增的策略

我们来看两个场景的执行对比。

场景 1 的线程图:
【性能学习】性能测试基础-编程知识网

场景 1 的 TPS 图:
【性能学习】性能测试基础-编程知识网

场景 1 的响应时间图:
【性能学习】性能测试基础-编程知识网

场景 2 的线程图:
【性能学习】性能测试基础-编程知识网

场景 2 的 TPS 图:
【性能学习】性能测试基础-编程知识网
场景 2 的响应时间图:
【性能学习】性能测试基础-编程知识网

这两个场景的比对如下:
【性能学习】性能测试基础-编程知识网

TPS 都是达到 400,但两个场景中线程递增的策略不同,产生的响应时间完全不同。虽然都没有报错,但是第一种场景是完全不符合真实的业务场景的。

场景 2 使用了递增的策略,在每个阶梯递增的过程中,出现了抖动,这就明显是系统设置的不合理导致的。设置不合理,有两种可能性:

  1. 资源的动态分配不合理,像后端线程池、内存、缓存等等;
  2. 数据没有预热。

那么,对于场景中线程(有些工具中叫虚拟用户)递增的策略,我们要做到以下几点:

  1. 场景中的线程递增一定是连续的,并且在递增的过程中也是有梯度的。
  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 增加了!
这就是我说的场景比对。

当我们不知道系统中哪个环节存在性能瓶颈时,对架构并不复杂的系统来说,可以使用这样的手段,来做替换法,以快速定位问题。

查看全文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/197536.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章:

【性能学习】性能测试基础-编程知识网

【性能学习】性能测试基础

学习链接:《性能学习实战30讲》 授课人:高楼 课程从三个部分进行阐述: 第一个模块是性能测试基础篇。在这个模块里澄清一些性能测试的基础概念,讲解一些关键部分。但并不是对概念的简单描述,而是根据实际项目&#xff……

【性能学习】性能测试基础-编程知识网

TCP的发送系列 — 发送缓存的管理(一)

由图可知,发送缓存暂时存放: 1. 应用程序传给发送TCP准备发送的数据。 2. TCP已发送出但尚未收到ack的数据。
发送窗口只是发送缓存的一部分。已发送但未被确认数据大小<发送窗口的大小。已被确认的数据会从发送缓存中删除。发送缓存和发送窗口后沿&……

【性能学习】性能测试基础-编程知识网

【Python百日进阶-WEB开发】Day167 – Django视图 View(二)

文章目录六、HttpResponse对象6.1 HttpResponse6.2 JsonResponse6.3 跳转页面七、状态保持3.7.1 Cookie3.7.1.1 第一次请求 设置cookie3.7.1.2 第二次请求 得到cookie3.7.1.3 cookie的生命周期3.7.1.4 删除cookie的两种办法设置COOKIE4、返回响应3.7.2 Session3.7.2.0 session ……

【性能学习】性能测试基础-编程知识网

A-Level经济例题解析及练习Demand Curve

今日知识点:Demand Curve
例题
Q: Demand Curve
Draw a demand curve for music downloads. What happens to it in each of the following scenarios? Why?
A. The price of iPods falls
B. The price of music downloads falls
C. The price of CDs falls
解析……

【性能学习】性能测试基础-编程知识网

网易对象存储NOS十周年:为什么能不被取代?(文末有福利)

谨以此文,献给曾经和现在为项目努力付出的小伙伴们,以及相信我们、陪伴项目共同成长的用户,并与业界就服务端产品如何保持生命力进行交流。2012年10月30日,网易杭州研究院(以下简称杭研)上线了一款新的存储……

【性能学习】性能测试基础-编程知识网

入门力扣自学笔记191 C++ (题目编号:1662)

1662. 检查两个字符串数组是否相等
题目:
给你两个字符串数组 word1 和 word2 。如果两个数组表示的字符串相同,返回 true ;否则,返回 false 。
数组表示的字符串 是由数组中的所有元素 按顺序 连接形成的字符串。 示例 1&……

【性能学习】性能测试基础-编程知识网

计算机毕设(附源码)JAVA-SSM基于疫情防控的超市管理系统

项目运行
环境配置:
Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术:
SSM mybatis Maven Vue 等等组成,B/S模式 M……

【性能学习】性能测试基础-编程知识网

win11开机音效设置的方法

微软为win11重做了开机音效,与我们一直以来使用的开机音效不太一样,听起来很不舒服,因此我们可以通过设置开机音效的方法来修改它,只要在个性化设置中就可以找到了,下面一起来试试看吧。
win11开机音效怎么设置&#……

【性能学习】性能测试基础-编程知识网

魔兽巫妖王服务端架设服务器搭建教程

魔兽巫妖王服务端架设服务器搭建教程新手必看
我是艾西,今天给想自己当服主的小伙伴简单说说开魔兽需要东西,还有一些操作步骤等
自己不懂技术可以开吗?当然可以,开服技术这是每个开服的小伙伴都要掌握的技术,不然后……

【性能学习】性能测试基础-编程知识网

vue3项目的创建,vite+vue3+ts(3)- router

vue3 有三种写法: 1.compostion API : 还是按照vue2.0写法 2.组合式API: 3. 组合式API 语法糖(setup), 语法简洁(推荐使用这个) 写法: 4. 在.eslintrc.cjs 或者 .eslintrc.js中配置代码,是这个……

【性能学习】性能测试基础-编程知识网

k8s学习-CKS真题-K8S安全策略PodSecurityPolicy

目录题目环境搭建解题参考题目 Task 使用 Trivy 开源容器扫描器检测 namespace kamino 中 Pod 使用的具有严重漏洞的镜像。 查找具有 High 或 Critical 严重性漏洞的镜像,并删除使用这些镜像的 Pod。 注意:Trivy 仅安装在 cluster 的 master 节点上&……

【性能学习】性能测试基础-编程知识网

STM32F103基于HAL库I2C/SPI硬件接口+DMA驱动 SSD1306 Oled

STM32F103基于HAL库I2C/SPI硬件接口DMA驱动 SSD1306 Oled✨由于手上只有I2C接口的SSD1306 OLED屏幕,仅测试了硬件I2C驱动显示功能,实际测试的FPS帧率在37或38变化。 📢本项目从Github开源项目中移植过来,开源地址:http……

【性能学习】性能测试基础-编程知识网

English Learning – L2 第 14 次小组纠音 复习元音 [ɔɪ ] [aʊ] [əʊ] [ɪə] 弱读 2023.4.12 周三

English Learning – L2 第 14 次小组纠音 复习元音 [ɔɪ ] [aʊ] [əʊ] [ɪə] 弱读 2023.4.12 周三共性问题coin voice /kɔɪn/ /vɔɪs/ 中 ɔɪvowel pounds /ˈvaʊəl/ /paʊndz/ 中的 aʊshow /ʃəʊ/beer nearly /bɪə/ /ˈnɪəlɪ/ 中的 ɪəbest bed ten /best/……

【性能学习】性能测试基础-编程知识网

LC-1157. 子数组中占绝大多数的元素(二分查找+随即猜,摩尔投票+线段树,upper_bound和lower_bound函数)

文章目录[1157. 子数组中占绝大多数的元素](https://leetcode.cn/problems/online-majority-element-in-subarray/)统计每个元素的索引-超时二分查找 随机猜摩尔投票 线段树[剑指 Offer 39. 数组中出现次数超过一半的数字](https://leetcode.cn/problems/shu-zu-zhong-chu-xi……

【性能学习】性能测试基础-编程知识网

杭州旭航集团,申请纳斯达克IPO上市,募资9800万美元

来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,为中国企业提供数字内容营销服务的杭州旭航网络科技有限公司的控股公司Xuhang Holdings Ltd(以下简称:旭航集团),近期已向美国证券交易委员会(SEC)提……

【性能学习】性能测试基础-编程知识网

深度学习快速参考:11~13

原文:Deep Learning Quick Reference 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何实现目……

【性能学习】性能测试基础-编程知识网

基于copula的风光联合场景生成与缩减

目录
1 主要内容
风光出力场景生成方法
2 部分程序
3 程序结果
4 程序链接
点击直达! 1 主要内容
该程序方法复现《融合风光出力场景生成的多能互补微网系统优化配置》风光出力场景生成部分,目前大多数研究的是不计风光出力之间的相关性影响&amp……

【性能学习】性能测试基础-编程知识网

TS 使用自动提示生成对象中的键

TS 使用自动提示生成对象中的键
使用 plain object 而不是 class 的原因主要是在于 redux 中保存的对象需要为可序列化的对象。当然,具体操实现的时候肯定是可以无视这个需求的,不过 Redux 团队强烈建议使用可序列化对象,具体的官方文档说明……

【性能学习】性能测试基础-编程知识网

Spring Boot概述(一)

1. SpringBoot 概述
1.1 SpringBoot 概念
SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的……

【性能学习】性能测试基础-编程知识网

计算机笔试/面试常见逻辑题/智力题汇总

说明:按种类汇总,难度不分先后,做了分级罗列,方便后续扩充,大家有比较有意思的题目可以在讨论区讨论。 下面有的题题解相对复杂的直接参考了网上的一些解答,而有的题解我认为并不好的也做了补充&#xff0c……