在性能分析的一般的步骤是:
ps:你应该记录每一步
可以从下面这些问题了解你的系统
(1)你能给我一个问题服务器的完整描述吗?
(2)你能告诉我到底是什么问题吗?
比如:拷贝大文件到服务器时会很慢。这就可能是网络或者磁盘子系统的问题
(3)谁遇到这个问题的
(4)问题可以重现吗?
(5)问题是什么时候开始的?它是很平缓的发生还是很快的发生?
(6)是否是对服务器使用方法不对之类的引起的?
(7)是否涉及到其他服务器或者硬件组件?
(8)是否有日志
(9)问题的优先级是什么?什么时候能解决?
(10)问题有多大规模
(11)这个问题相关的费用是多少
对性能瓶颈做出判断是性能分析的第一步,有了问题才能分析调优。
很多人在描述性能测试的过程中,说要找到性能测试中曲线上的“拐点”,但是大部分系统其实是没有明确的拐点的。
举例来说,TPS 的视图如下:
显然,这是一个阶梯式增加的场景,非常好。但是拐点在哪呢?有人说,显然在 1200TPS左右的时候。也有人说了,显然是到 1500TPS 才是拐点呀。但是也有人说,这都已经能到2000TPS 了,显然 2000TPS 是拐点。
我们再来看一下这张图对应的响应时间视图:
其实这些对拐点的判断,都是不合理的。如果我们对 TPS 的增加控制得更为精准的话,那么这个 TPS 的增加是有一个有清晰的弧度,而不是有一个非常清晰的拐点。
但是至少我们可以有一个非常明确的判断,那就是瓶颈在第二个压力阶梯上已经出现了。因为响应时间增加了,TPS增加的却没有那么多,到第三个节点时,显然增加的TPS更少了,响应时间也在不断的增加,所以,性能瓶颈在加剧,越往后越明显。
那么我们的判断就是:
如果你觉得上面的瓶颈还算清晰的话,那么我们再来看一张图:
在这个 TPS 的曲线中,你还能判断出拐点在哪吗?
显然是判断不出来拐点的,但是我们根据图得出以下几个结论:
我们再来看一个TPS图
看到这张图,是不是明显感觉系统有瓶颈呢?那么瓶颈是不是和压力大小有关呢?
这种比较有规律的问题,显然不是压力大小的原因。为什么呢?因为TPS周期性的出现降低,并且最大的TPS也都恢复到了差不多的水位上。所以,即使是压力降低,也最多降低最大的 TPS 水位,会让问题出现得更晚一点,但是不会不出现。
综合以上,如果画一个示意图的话,TPS 的衰减过程大概会如下所示:
在这样的趋势图中,我们是看不到明确的拐点的。但是我们能做到的清晰的判断就是:有瓶颈!
所以对TPS曲线来讲,它可以明确告诉我们的就是:
这时你可能就会问,为什么不看响应时间就武断的下此结论呢?因为响应时间是用来判断业务有多快的,TPS才是用来判断容量有多大的
我们还是来看看响应时间,下面看一张响应时间图:
它对应的线程图是:
多明显的问题,随着线程的增多,响应时间也在增加,是吧。再来看它们对应的 TPS 图:
到第 40 个线程时,TPS 基本上达到上限,为 2500 左右。响应时间随着线程数的增加而增加,系统的瓶颈显而易见的出现了。
但是,如果只让你看TPS曲线,你是不是也会有同样的判断?那就是:有瓶颈!并且和压力有关?所以说,TSP就可以告诉我们系统有没有瓶颈了,而响应时间是用来判断业务有多快的
讲完响应时间之后,我们再来看下线程递增。
在见识了很多性能测试人员做的场景之后,必须得承认,有些场景的问题太多了。
首先,我们来看两个场景的执行对比。
场景 2 的 TPS 图:
场景 2 的响应时间图:
这两个场景的比对如下:
对的!
TSP都是达到400,但是两个场景中线程递增的策略不同,产生的响应时间完全不同。虽然都没有报错,但是第一种场景是完全不符合真实的业务场景的。这是为什么?
在场景的执行中,首先,响应时间应该是从低到高的,而在场景1中并不是这样。其次,线程应该是递增的,而场景1并没有这样做(秒杀场景怎么算?)。最后,在两个场景中,TPS的上限都达到了400TPS。但是你可以看到,在场景2中,只要40个线程就可以达到,但场景1中用了500线程,显然压力过大,所以响应时间才那么长。
其实在生产环境中,像场景 1 这样的情形是不会出现的。如果它出现了,那就是你作为性能测试的责任,因为你没有给出生产环境中应该如何控制流量的参数配置说明。
同时,我们从上面的场景对比可以看到,对一个系统来说,如果仅在改变压力策略(其他的条件比如环境、数据、软硬件配置等都不变)的情况下,系统的最大 TPS 上限是固定的。
场景2使用了递增的策略,在每个阶梯递增的过程中,出现了抖动,这明显是系统设置的不合理导致的。设置不合理,有两种可能性:1、资源的动态分配不合理,像后端线程池、内存、缓存等等;2、数据没有预热
我们再回到之前说的秒杀场景。
那么,对于线程中场景(有的工具叫做虚拟用户)递增的策略,我们要做到下面几点:
这里给出一些做性能场景递增的经验值:
当然这里也不会是放在哪个系统中都适合的递增幅度,你还是要根据实际的测试过程来做相应的判断。
有了这些判断之后,相信大家都能做出合理的场景来了。
有了瓶颈的判断能力,也有了线程递增的意识,那么下面在场景执行中,我们就要有判断性能衰减的能力了吧。
来,我们先看一个压力过程中产生的结果图。
在递增的压力过程中,随着用户数的增加。我们可以做几次计算。
通过这三次计算,我们是不是可以看到,每线程每秒发出的请求数在变少,但是整体 TPS是在增加的。
我们有很多做性能测试的人,基本上,只看 TPS 和响应时间的时候,在上面这个示例中,肯定会一直往上加用户。虽然响应时间在增加,但是增加得也不多嘛。
但实际上,通过我们的计算可以知道,性能是在不断地衰减的。我们来看一张统计图:
通过红线的大致比对可以知道,当每线程每秒的请求数降到 55 左右的时候,TPS 就达到上限了,大概在 5000 左右,再接着往上增加线程已经没有用了,响应时间开始往上增加了。
这就是性能衰减的过程(题外话,在上图中,其实还有一个问题,就是在红线前面,性能在上升的过程中有几次抖动,这个抖动到后面变大了,也变频繁了,如果这是必然出现的抖动,那也是配置问题,希望你注意到这一点)。
为什么要这么细致地描述性能衰减的过程呢?
其实就是告诉你,只要每线程每秒的TPS开始变少,就意味着性能瓶颈已经出现了。但是瓶颈出现之后,并不是说服务器的处理能力(一般用TPS描述)会下降,应该说TPS仍然会上升,在性能不断衰减的过程中,TSP就会达到上限
也就会说,性能瓶颈其实在最大TPS之前早就已经出现了
那么我们是不是应该在性能衰减到最大TPS时就停止场景呢?这个不一定哦。
在性能分析中,响应时间的拆分通常是一个分析起点。因为在性能场景中,不管是什么原因,只要系统达到了瓶颈,再接着增加压力,肯定会导致响应时间上升,直到超时为止。
在判断了瓶颈之后,我们需要找到问题出现在什么地方。在压力工具上看到的响应时间,都是经过了后端的每一个系统的。
那么,当响应时间边长,我们就要知道,它在哪个阶段变长了。
我们看下这张图
这应该是最简单的一个压力测试逻辑了。一个应用,一个 DB,结果也拆分出了 8 个时间段,这还是在我没有加上压力工具自己所消耗的时间的情况下。
如果我们要分析压力工具中的响应时间,拆分的逻辑就是上面这个示意图。
但是在真实的场景中,基本上不是这样的。如果是内网,那基本上都是连在一个交换机上,所以通常是这样的:
在这样的拓扑中,我们仍然可以拆出来 t1 到 t8 的时间。只是实际动手的时候,思路一定要清晰,时间拆分是从哪里到哪里,要画出来,不能混乱。
我们有很多手段可以进行时间的拆分,当然要看我们的应用支持哪一种。
其实不管我们用什么样的工具来监控,最终我们想得到的无非是每个环节消耗了多长时间。用日志也好,用链路监控工具也好,甚至抓包都可以。
当我们拆分到了某个环节之后,就有了下一步的动作:构建分析决策树。
分析决策树,对性能测试分析人员实在太重要了,是性能分析中不可或缺的一环。它是对架构的梳理,是对系统的梳理,是对问题的梳理,是对查找证据链过程的梳理,是对分析思路的梳理。它起到纵观全局,高屋建瓴的指导作用
性能做到了艺术的层级之后,分析决策树就是提炼出来的,可以触类旁通的方法论。
应该说,所有的技术行业在面对自己的问题时,都需要有分析决策树。再广而推之的话,所有的问题都要有分析决策树来协助。
通过上面的几个步骤,我们就会知道时间消耗在了哪个节点上。那么之后呢?又当如何?
总要找到根本的原因才可以吧,如下有个分析决策图:
从压力工具中,只需要知道TPS、响应时间和错误率三条曲线,就可以明确判断瓶颈是否存在。再通过分段分层的策略,结合监控平台,日志平台,或者其他的实时分析平台,知道了架构中哪个环节有问题,然后再根据更细化的架构图一一拆解下去。
这里,以数据库分析和操作系统分析举一下例子。
首先我们看一下数据库分析决策树。
比如针对 RDBMS 中的 MySQL,我们就可以画一个如下的决策树:
由于这里面的内容实在过多,无法一次性展现在这里。我举几个具体的例子给你说明一下。
MySQL中的索引统计信息有配置值,有状态值。我们要根据具体的结果来判断是否需要增加key_buffer_size值的大小。比如这种就无所谓了
从上面的数据可以看到,key buffer size 就用到了 4%,显然不用增加。
再比如,我们看到这样的数据:
这就明显有问题了。配置值为 2000 的 Open Table Cache,已经被占满了。显然这里需要分析。但是,看到状态值达到配置值并不意味着我们需要赶紧加大配置值,而是要分析是否合理,再做相应的处理。比如说上面这个,Table 确实打开得多,但是如果我们再对应看下这一条。
你是不是觉得应该先去处理慢 SQL 的问题了?
关于数据库的我们就不举更多的例子了。在这里只是为了告诉你,在分析决策树的创建过程中,有非常多的相互依赖关系。
然后我们再来看一下操作系统分析决策树,我在这里需要强调一下,操作系统的分析决策树,不可以绕过。
基于此决策树,每个人都可以做到对操作系统中性能问题的证据链查找。
举个例子:
上面,中断能占 40%,sy CPU 也能占 40%。这系统还用干业务的事吗?全干自己的事去了,可见操作系统有问题!你是不是要做这个判断了?
而实际情况是,这个主机上只有一个网卡队列,而请求量又比较大。
所以要解决的是网卡队列的问题,至于怎么解决,那手段就多了。可以换个服务器,可以多加几个队列,可以多接几个节点…
以上只是给出几个性能分析过程中常见的决策树示例。在后续的分析过程实例中,我们将秉承着这种分析思路,一步步地走到瓶颈的面前。
为什么要写这一部分呢?因为我看到很多人对瓶颈的判断,并不那么精确,所以想写一下场景比对的建议。
其实简单来说,就一句话:当你觉得系统中哪个环节不行的时候,又没有能力分析它,你可以直接做该环节的增加。
举个例子,我们有一个如下的架构:
可以得到这样的结果:
从TPS曲线中,我们可以明显看到系统是有瓶颈的,但是并不知道在哪里。鉴于系统架构如此简单,我们索性在某环节上加上一台服务器,变成这样:
然后得到如下数据:
哟,没好使!
怎么办?再接着加其他节点,我加了更多的 JMeter 机器。
再来看下结果:
真巧,TPS 增加了!
看到了吧,这就是我说的场景比对。
当我们不知道系统中哪个环节存在性能瓶颈时,对架构并不复杂的系统来说,可以使用这样的手段,来做替换法,以快速定位问题。