众所周知,对性能瓶颈作出判断是性能测试的第一步,只有发现问题后,才能进行后续的调优和性能提升。今天我们就一起使用jmeter对某个http的接口进行不同策略的压测,通过一些图表和数据来分析系统的性能瓶颈。
在对http接口进行压力测试之前,我们先来简单回顾一下什么是http协议。HTTP(超文本传输协议)规定了传输的规则,HTML(超文本标记语言)规定了内容的规则。下图是HTTP大体的交互过程:

在网络请求传输的过程中,数据经过了Frame\Ethernet\IP\TCP\HTTP这些层面。不论是发送还是接受,都会经过这些层。在每次发送的过程中,每经过一层,都会给这个消息加上自己所在层的头信息。我们在进行性能测试的时候,还是主要关心的HTTP层的内容,分别是:
protocol
method
path
重定向
content-coding
超时设置
HTTP层压缩机制
浏览器并发限制
...
我们常见的浏览器并发限制如下:

除了浏览器限制以外,其余的配置在jmeter中均有相应的参数可以配置。
除了这些,我们主要关心的部分就是传输字节的大小,http的头信息以及body信息等。

我们在jmeter里创建一个线程组,设置最终的目标是200个线程,ramp-up时间设置为30s,也就是说在30s,会创建出200个线程并发出请求,并且设置了压力测试持续时间为60s。

运行后,从下面的线程图中可以看出在30s的时候创建出了所有200个线程

通常来说,随着用户数的增加,系统的响应时间也会慢慢增加。TPS前期也是一直在增加,但是会随着用户数到达一定的数量而幅度减缓,最终变平。所以,通过TPS的曲线,我们可以明确知道系统有没有瓶颈,以及TPS、响应时间和压力之间的关系是什么。

从下面实际运行后的TPS图中可以看出,TPS在23秒之前一直处于上升阶段,从9TPS升到了20TPS,23s左右的时候TPS已经接近最大值,且开始出现绿色代表的失败的请求。

对照着看一下响应时间的图,可以看到响应时间随着线程数越来越多,呈线性增长,23s之后出现了一波响应时间的激增,开始出现大量的超时请求,和TPS图中绿色的曲线的时间基本吻合,在23s达到最大TPS时,响应时间大概需要5.6s。

于是,我们换一种线程递增的压力策略,如下图配置,同样是最终达到200个线程,最开始的时候只启动10个线程,接下来每10秒添加10个线程,10个线程在1s的时间内创建出并发出请求,启动线程达到最大200个之后,继续持续压力运行60s。

这种压力策略之下,我们看下TPS图,在45s左右的时候,TPS趋于最大值20TPS,这和第一种压力策略中的最大TPS基本一致,也变相说明TPS的峰值和压力策略无关。

再来看下响应时间图,随着线程数的缓慢增多,响应时间也越来越久,但是可以发现在这种递增压力策略之下的响应时间明显比方案一中的响应时间要短,在45s达到最大TPS的时候,响应时间只需要2s左右。

我们来对比一下这两种压力策略的数据:
| 对比项 | 场景一 | 场景二 |
| 线程数 | 30s内加到200个并发 | 10个线程有梯度地递增,最终加到200个并发 |
| TPS | 最大20TPS | 最大20TPS |
| 响应时间 | 5.6s | 2s |
| 错误率 | 9.41% | 7.69% |
对比之后发现,虽然两个场景的TPS 都能达到20,但是两个场景中的线程的压力策略完全不同,从而导致了响应时间的差异。从场景二中发现,只要40个线程就可以达到最大TPS,而场景一中30s就增加到200个线程,显然压力过大,导致后面的响应时间的激增和大量请求超时。
随着TPS达到20上限后,再继续加压力,服务的性能是处于一个衰减的状态,响应时间也会蹭蹭往上增加,此时性能瓶颈也就出现了。
总结一下,要准确地判断瓶颈点,可以通过TPS曲线来发现。要确定我们设置的性能场景是正确的,除非是秒杀的场景,否则不要一下子上来就几百个线程,而是应该逐渐递增的。在明确了有性能瓶颈后,下一步就是构建性能分析决策树和查找瓶颈证据链了。
今天的学习就到这里,如果这篇文章对你有帮助,请点赞和转发哦👍




