性能问题分析
性能优化的目标
- 后端:RT、TPS、并发数、Throughput、Footprint、Latency
- TPS和RT的影响因素:数据库读写、RPC、网络IO、逻辑计算复杂度、JVM
- WEB端:首屏时间、白屏时间、可交互时间、完全加载时间…
- 移动端:端到端的响应时间、Crash率、内存使用率、FPS…
影响性能的关键因素
- 产品设计:产品逻辑、功能交互、动态效果、页面元素
- 基础网络:网络=连接介质+计算终端
- 连接介质:电缆、双绞线、光纤、微波、载波或通信卫星
- 计算终端:PC、手机、可穿戴设备、家具家电
- 基础网络设施:互联网、局域网、城域网、广域网
- 代码质量与架构
- 架构不合理
- 研发功能和经验不足
- 没有性能意识:只实现了业务功能不注意代码性能,新功能上线后整体性能下降,或当业务上量后系统出行连锁反应,导致性能问题叠加,直接影响到用户体验。
- 移动端环境
- 硬件及云服务
压力测试
基本概念
压力测试(英语:Stress testing)是针对特定系统或是组件,为要确认其稳定性而特意进行的严格测试。会让系统在超过正常使用条件下运作,然后再确认其结果。
压力测试是对系统不断施加压力,来预估系统服务能力的一种测试。
为什么对系统压测呢?有没有必要。压不压测要看场景!
一般而言,只有在系统基础功能测试验证完成、系统趋于稳定的情况下,才会进行压测。
配置环境信息
- server a:数据库与缓存服务器4c 4g:mysql、redis、mq、es
- server b:CICD服务器 3C 2G:Ngxin、Jmter、CICD
- server c:应用服务器 3C 2G:application
- server d:应用服务器 3C 2G:Grafana、Prometheus、InfluxDB
压测目的
1.当负载逐渐增加时,观察系统各项性能指标的变化情况是否有异常
2.发现系统的性能短板,进行针对性的性能优化
3.判断系统在高并发情况下是否会报错,进程是否会挂掉
4.测试在系统某个方面达到瓶颈时,粗略估计系统性能上限
以上主要的四种性能指标【响应时间、并发用户数、吞吐量、资源使用率】它们之间存在一定的相关性,共同反映出性能的不同方面。
在这个图中,定义了三条曲线、三个区域、两个点以及三个状态描述。
- 三条曲线
- 吞吐量的曲序,紫色
- 利用率,绿色
- 相应时间曲线,深蓝色
- 三个区域
- 轻负载区,Light Load
- 重负载区,Heavy Load
- 坍陷区,Buckle Zone
- 两个点
- 最优并发用户数,The Optimum Number if Concurrent Users
- 最大并发用户数,The Maximum Number of Concurrent Users
- 三个状态描述:
- 资源饱和,Resource Saturated
- 吞吐下降,Throughput Falling
- 用户受影响,End Users Effected
常用压测工具:
Apache JMeter : 可视化的测试工具
Apache的ab压力测试
Nginter 韩国研发
PAS 阿里测试工具
MeterSphere :国内持续测试的开源平台
Apache JMeter它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。
JMeter压测环境架构图:
压测实战案例
步骤:
创建测试计划
配置线程组、http请求、断言、结果监听器
执行测试
查看测试结果,分析测试结果
实现:
1)新建测试计划
2)配置线程组:
线程属性说明:ramp-up背后含义不好理解,案例做完有详细解释
- 线程数:20, 线程数量,这里设置了20个线程
- ramp-up:表示在指定时间之内把这些线程全部启动起来。 如果n=1,那就表示要在1s以内把50个线程全部启动起来。
- 循环次数:2000,表示把 20 thread 循环2000次,也就是说让每一个请求接口循环调用接口2000次
3)配置HTTP接口:
http://ip:port/xx/xx/10000005620800
选择keepalive方式,表示使用了长连接。使用长连接可以防止频繁的建立连接,关闭连接消耗性能。一般浏览器都支持keepalive,如果这里不勾选,这样我们的压测的部分性能消耗会发生在建立,关闭连接上,导致我们的压测数据不准确。
4)配置断言:
JMeter断言常用有两种,一种是响应断言,一种是响应时间断言,如果响应内容不满足断言的配置,则认为这次的请求是失败的。
- 响应断言:判断响应内容是否包含指定的字符信息,用于判断api接口返回内容是否正确。
- 响应时间断言:判断响应时间,是否超过预期的时间,用于判断api接口返回时间是否超过预期。
断言添加方式:右击测试计划的http请求,选择添加–>断言–>加响应断言和断言持续时间。
(1)配置响应断言:我们接口正常返回code值为20001,如果接口返回code值不是20001表示接口异常,为了测试,这里修改为接口返回code值不为20001则表示访问失败。
(2)配置断言响应时间:设置请求接口时间超过3毫秒,则认为请求失败。
(3)验证断言配置:发起http请求,由于返回内容code值不为20000,以及访问时间超过10毫秒,所以认为访问失败。
5)配置结果监听:
配置监听器:监听压测结果【聚合报告和汇总结果很类似,看一个就行】
聚合报告:查询结果信息聚合汇总,例如样本、平均值、通吐量、最大值、最小值…
察看结果树:记录每一次压测请求
图像结果:分析了所有请求的平均值、终止、偏离值和通吐量之间的关系。
汇总结果:汇总压测结果
汇总图:将压测结果以图像形式展示
压测结果
1)聚合报告:
- 样本(sample): 发送请求的总样本数量
- 响应时间【单位ms】:
- 平均值(average):平均的响应时间
- 中位数(median): 中位数的响应时间,50%请求的响应时间
- 90%百分位(90% Line): 90%的请求的响应时间,意思就是说90%的请求是<=1765ms返回,另外10%的请求是大于等于1765ms返回的。
- 95%百分位(95% Line): 95%的请求的响应时间,95%的请求都落在1920ms之内返回的
- 99%百分位(99% Line): 99%的请求的响应时间
- 最小值(min):请求返回的最小时间,其中一个用时最少的请求
- 最大值(max):请求返回的最大时间,其中一个用时最大的请求异常(error): 出现错误的百分比,错误率=错误的请求的数量/请求的总数
- 异常(error): 出现错误的百分比,错误率=错误的请求的数量/请求的总数
- 吞吐量TPS(throughout): 吞吐能力
- Received KB/sec—-每秒从服务器端接收到的数据量
- Sent KB/sec—-每秒从客户端发送的请求的数量
2)察看结果树:
记录了样本中的每一次请求
3)汇总图与图形结果
参考意义不大,且见文知意,所以略!
图形结果:分析了所有请求的平均值、终止、偏离值和通吐量之间的关系
横坐标:为请求数量,单位个数
纵坐标:响应时间,单位ms
4)汇总报告【类似于聚合报告】
- 样本(sample): 发送请求的总样本数量
- 响应时间【单位ms】:
- 平均值(average):平均的响应时间
- 最小值(min):请求返回的最小时间,其中一个用时最少的请求
- 最大值(max):请求返回的最大时间,其中一个用时最大的请求
- 标准偏差:度量响应时间分布的分散程度的标准,衡量响应时间值偏离平均响应时间的程度。标准偏差越小,偏离越少,反之亦然。
- 异常(error): 出现错误的百分比,错误率=错误的请求的数量/请求的总数
- 吞吐量TPS(throughout): 吞吐能力,这个才是我们需要的并发数每秒接收 KB/sec—-每秒从服务器端接收到的数据量
- 每秒发送KB/sec—-每秒从客户端发送的请求的数量
- 平均字节数
看到的是最终的结果数据!线性变化趋势
线程组配置详解
01-线程数:用来发送http请求的线程的数量
线程组常用来模拟一组用户访问系统资源(API接口)。
假如客户机没有足够的能力来模拟较重的负载,可以使用JMeter的分布式测试功能,通过一个JMeter的Master来远程控制多个JMeter的Salve完成测试。
02-循环次数:循环执行多少次操作
循环次数表示了循环执行多少次操作!循环次数直接决定整个测试单个线程的执行时间,和整体测试执行时间。
单线程执行时间 = 单请求平均响应时间 循环次数
整个测试耗时 = 单线程执行时间 + (Ramp-Up - Ramp-Up / 线程数)
03-Ramp-Up:建立全部线程耗时
- Ramp-Up Period (in-seconds) 代表隔多长时间执行,默认值是0,0代表同时并发。用于告知JMeter 要在多长时间内建立全部的线程。
JMeter常用插件
已有内容的分析维度不够:需要加入新的插件
- TPS、QPS
- RT【平均响应时间】
- 压力机活动线程数
- 服务器资源信息
开启插件下载:
下载地址:http://jmeter-plugins.org/downloads/all/,官网上下载plugins-manager.jar直接在线下载,然后执行在线下载即可。
1、PerfMon:监控服务器硬件,如CPU,内存,硬盘读写速度等
Allows collecting target server resource metrics
2、Basic Graphs:主要显示平均响应时间,活动线程数,成功/失败交易数等
Average Response Time 平均响应时间
Active Threads 活动线程数
Successful/Failed Transactions 成功/失败 事务数
3、Additional Graphs:主要显示吞吐量,连接时间,每秒的点击数等
Response Codes
Bytes Throughput
Connect Times
Latency
Hits/s
01-配置插件
如果可以配置如下三个监听器,就表示插件已经安装成功!执行压力测试,就可以看见压测的每秒事务数、响应时间,活动线程数等压测结果
- 响应时间:jp@gc - Response Times Over Time
- 活动线程数:jp@gc - Active Threads Over Time
- 每秒事务数:jp@gc - Transactions per Second
响应时间:jp@gc - Response Times
活动线程数:jp@gc - Active Threads
每秒事务数:jp@gc - Transactions per Second
02-性能关键指标分析
1)RT:响应时间
平均值: 请求响应的平均时间是332ms
中位数: 50%请求响应时间都在8ms之内
P90: 90%的请求都在514ms之内响应结束
P95: 95%的请求都在1051ms之内响应结束
P99:99%的请求都在6979ms之内响应结束
最小值: 请求响应最小时间2ms
最大值: 请求响应的最大时间是35s
2)压力机活动线程数
压力机活动线程数表明压测过程中施加的压力的情况
3)TPS: 每秒的事务数
数字愈大,代表性能越好;
4)QPS: 每秒的查询数量
数字愈大,代表性能越好;(1tps >= QPS)
5)吞吐量: 每秒的请求数量
数字愈大,代表性能越好;
服务器硬件资源监控【精简版】
压测的时候,我们需要实时了解服务器【CPU、内存、网络、服务器Load】的状态如何,哪如何监控服
务器的资源占用情况呢?方法有很多种:
使用操作系统命令:top、vmstat、iostat、iotop、dstat、sar…
使用finalshell
使用JMeter压测工具perfmon
使用Grafana+Prometheus+node_exporter
监控原理:
01-配置服务端代理
注意:服务器硬件资源的监控,必须在服务端安装serverAgent代理服务,jmeter才能实现监控服务端
的cpu、内存、io的使用情况。
ServerAgent下载地址:https://github.com/undera/perfmon-agent/blob/master/README.md
## 默认启动运行 startAgent.sh 脚本即可
## 服务启动默认4444端口,根本连接不上,因此自己创建一个部署脚本文件对此进行部署,且把端口修
改为7879
nohup java -jar ./CMDRunner.jar --tool PerfMonAgent --udp-port 7879 --tcpport 7879 > log.log 2>&1 &
## 赋予可执行权限
chmod 755 startAgent.sh
启用7879端口后,服务器的cpu,io,内存使用情况就顺利的监控到了。
02-监控CPU:
Elapse time:消耗时间
Performance Metrics:性能指标
- idle:CPU空闲
- iowait:IO等待
- system:系统占用
- CPU user:CPU用户占用
03-监控网络:
- 接收字节:byteSrecv【单位:比特、KB、MB】
- 发送字节:byteSent【单位:比特、KB、MB】
- 发送(transport):tx
- 接收(receive):rx
04-监控内存:
- usedPerc:每分钟使用内存【单位:字节、KB、MB】
- freePerc:每分钟未使用内存【单位:字节、KB、MB】
05-监控系统整体负载情况:
服务器上执行以下命令:
#查询服务器资源使用情况
top
top -H
如下图所示,可以看到系统负载 load average 情况,1分钟平均负载,5分钟平均负载,15分钟平均负
载分别是 0.08, 0.03, 0.05 ;
统计信息区前五行是系统整体的统计信息:
06-性能关键指标分析Load Average
1)服务器:CPU、内存、网络IO
CPU
内存
网络IO
2)系统负载: load average
- 什么是Load Average?
- 系统负载System Load是系统CPU繁忙程度的度量,即有多少进程在等待被CPU调度(进程等待队列的长度)。
- 平均负载(Load Average)是一段时间内系统的平均负载,这个一段时间一般取1分钟、5分钟、15分钟。
- 多核CPU和单核CPU的系统负载数据指标的理解还不一样。
维基百科定义:In Unix computing, the system load is ameasure of the amount of computational work that a computer system performs.
在类Unix系统中,系统负载是衡量计算机系统执行的计算工作量的指标。
举个栗子:while(true) 这样程序不耗时,cpu会飙高,但是load average不会走高。说明程序在计算,
但是并没有执行耗时工作,所以Load Average并不高。我们在核查服务器负载因需要重点关注load average。
- Load的数值是什么含义?
不同的CPU性质不同:单核,双核,四核 –>>
单核CPU三种Load情况
- 举例说明:把CPU比喻成一条(单核)马路,进程任务比喻成马路上跑着的汽车,Load则表示马路的繁忙程度。
- 情况1-Load小于1:不堵车,汽车在马路上跑得游刃有余:
- 情况2-Load等于1:马路已无额外的资源跑更多的汽车了:
- 情况3-Load大于1:汽车都堵着等待进入马路:
双核CPU
- 如果有两个CPU,则表示有两条马路,此时即使Load大于1也不代表有汽车在等待:
- [Load==2,双核,没有等待]
- 什么样的Load值得警惕?
如下分析针对单核CPU
【0.0 - 0.7】 :系统很闲,马路上没什么车,要考虑多部署一些服务
【0.7 - 1.0】:系统状态不错,马路可以轻松应对
【等于1.0】 :系统马上要处理不多来了,赶紧找一下原因
【大于5.0】 :马路已经非常繁忙了,进入马路的每辆汽车都要无法很快的运行
- 不同Load值说明什么问题?
如下分析针对单核CPU的四种情况:
情况1:1分钟负载 > 5,5分钟负载 < 1,15分钟负载 < 1
举例: 5.18 , 0.05 , 0.03
短期内繁忙,中长期空闲,初步判断是一个“抖动”或者是“拥塞前兆”
情况2:1分钟负载 > 5,5分钟负载 > 1,15分钟负载 < 1
- 举例: 5.18 , 1.05 , 0.03
- 短期内繁忙,中期内紧张,很可能是一个“拥塞的开始”
情况3:1分钟负载 > 5,5分钟负载 > 5,15分钟负载 > 5
- 举例: 5.18 , 5.05 , 5.03
- 短中长期都繁忙,系统“正在拥塞”
情况4:1分钟负载 < 1,5分钟负载 > 1,15分钟负载 > 5
- 举例: 0.18 , 1.05 , 5.03
- 短期内空闲,中长期繁忙,不用紧张,系统“拥塞正在好转
压测监控平台
Docker+JMeter+InfluxDB+Grafana+node_exporter
配置Docker环境
#yum 包更新到最新
sudo yum update -y
#安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#设置yum源为阿里云
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker.ce/linux/centos/docker-ce.repo
#安装docker
sudo yum install docker-ce -y
systemctl start docker
docker -v
安装InfluxDB
#docker安装influxDB
docker pull influxdb:1.8
#启动InfluxDB的容器,并将端口 8083 和 8086 映射出来:
docker run -d --name influxdb -p 8086:8086 -p 8083:8083 influxdb:1.8
#进入容器内部,创建名为jmeter的数据库
docker exec -it influxdb /bin/bash
influx
create database jmeter
show databases
#使用JMeter 库, select 查看数据,这个时候是没有数据的:
use jmeter
select from jmeter
设置JMeter脚本后置监听器
1)配置后置监听器
想要将 JMeter的测试数据导入 InfluxDB ,就需要在 JMeter中使用 Backend Listener 配置
2)主要配置说明
implementation 选择 InfluxDB所对应的:
- influxdbUrl:需要改为自己influxdb的部署ip和映射端口,我这里是部署在阿里云服务器,所以就是xxx.xxx.xxx.xxx,口是容器启动时映射的xx端口,db后面跟的是刚才创建的数据库名称
- application:可根据需要自由定义,只是注意后面在 grafana 中选对即可
- measurement:表名,默认是 jmeter ,也可以自定义summaryOnly:选择true的话就只有总体的数据。false会记录总体数据,然后再将每个
- transaction都分别记录
- samplersRegex:样本正则表达式,将匹配的样本发送到数据库
- percentiles:响应时间的百分位P90、P95、P99
- testTitle:events表中的text字段的内容
- eventTags:任务标签,配合Grafana一起使用
influxdbMetricsSender
org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender
influxdbUrl http://47.93.59.248:8086/write?db=jmeter
application hero_mall_one
measurement jmeter
summaryOnly false
samplersRegex RT
percentiles 90;95;99
testTitle 压力测试案例01
eventTags
3)运行验证
运行 Jmeter 脚本,然后再次在 influxdb 中查看数据,发现类似下面的数据说明输入导入成功:
安装Grafana
1)下载Grafana镜像:
docker pull grafana/grafana
docker run -d --name grafana -p 3000:3000 grafana/grafana
2)验证部署成功
网页端访问http://ip:port验证部署成功
默认账户密码:admin\admin
3)选择添加数据源
4)找到并选择 influxdb
5)配置数据源
数据源创建成功时会有绿色的提示:
6)导入模板
模板导入分别有以下3种方式:
- 直接输入模板id号
- 直接上传模板json文件
- 直接输入模板json内容
7)找展示模板
在Grafana的官网找到我们需要的展示模板
- Apache JMeter Dashboard
- dashboad-ID:5496
- JMeter Dashboard(3.2 and up)
- dashboad-ID:3351
8)导入找到的模板,使用模板id
导入模板,我这里选择输入模板id号,导入后如下,配置好模板名称和对应的数据源,然后 import 即可
9)查看效果
展示设置,首先选择创建的application
注意: 如果我们修改过表名,也就是在jmeter的Backend Listener的measurement配置(默认为jmeter),这个时候就需要去设置中进行修改,我这里使用的就是默认的,所以无需修改。
安装node_exporter
# 下载
wget -c
https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_ex
porter-0.18.1.linux-amd64.tar.gz
# 解压
mkdir /usr/local/hero/
tar zxvf node_exporter-0.18.1.linux-amd64.tar.gz -C /usr/local/hero/
# 启动
cd /usr/local/hero/node_exporter-0.18.1.linux-amd64
nohup ./node_exporter > node.log 2>&1 &
注意:在被监控服务器中配置开启端口9100
安装Prometheus
1)下载解压运行
# 下载
wget -c
https://github.com/prometheus/prometheus/releases/download/v2.15.1/prometheus
-2.15.1.linux-amd64.tar.gz
# 解压
tar zxvf prometheus-2.15.1.linux-amd64.tar.gz -C /usr/local/hero/
cd /usr/local/hero/prometheus-2.15.1.linux-amd64
# 运行
nohup ./prometheus > prometheus.log 2>&1 &
2)配置prometheus
在prometheus.yml中加入如下配置:
- job_name: 'hero-Linux'
static_configs:
- targets:
['172.17.187.78:9100','172.17.187.79:9100','172.17.187.81:9100']
3)测试Prometheus
测试Prometheus是否安装配置成功
4)在Grafana中配置Prometheus的数据源
5)Grafana导入Linux展示模板
导入Linux系统dashboard
- Node Exporter for Prometheus Dashboard EN 20201010
- dashboard-ID: 11074
- Node Exporter Dashboard
- dashboard-ID: 16098
梯度压测:分析接口性能瓶颈
以上主要的四种性能指标【响应时间、并发用户数、吞吐量、资源使用率】它们之间存在一定的相关性,共同反映出性能的不同方面。
压测接口:响应时间20ms,响应数据包3.8kb,请求数据包0.421kb
http://ip:9001/spu/goods/10000005620800
压测配置
情况01-模拟低延时场景,用户访问接口并发逐渐增加的过程。
预计接口的响应时间为20ms
- 线程梯度:5、10、15、20、25、30、35、40个线程
- 循环请求次数5000次
- 时间设置:Ramp-up period(inseconds)的值设为对应线程数
- 测试总时长:约等于20ms x 5000次 x 8 = 800s = 13分
- 配置断言:超过3s,响应状态码不为20000,则为无效请求
机器环境
- 应用服务器配置:4C8G
- 外网-网络带宽25Mbps (峰值)
- 内网-网络带宽基础1.5/最高10Gbit/s
- 集群规模:单节点
- 服务版本:v1.0
- 数据库服务器配置:4C8G
Mbps : Megabit per second (Mbit/s or Mb/s)
MB/s : Megabyte per second
1 byte = 8 bits
1 bit = (1/8) bytes
1 bit = 0.125 bytes
1 megabyte = 10002 bytes
1 megabit = 10002 bits
1 megabit = 0.125 megabytes
1 megabit/second = 0.125 megabytes/second
1 Mbps = 0.125 MB/s
结论:
1 Gbit/s = 1 Gbps = 125 MB/s
1 Mbps = 0.125 MB/s
配置监听器:
聚合报告:添加聚合报告
查看结果树:添加查看结果树
活动线程数:压力机中活动的线程数
TPS统计分析:每秒事务树
RT统计分析:响应时间
后置监听器,将压测信息汇总到InfluxDB,在Grafana中呈现
压测监控平台:
JMeter DashBoard
应用服务器:内存、网络、磁盘、系统负载情况
MySQL服务器:内存、网络、磁盘、系统负载情况
性能瓶颈剖析
1)梯度压测,测出瓶颈
进一步提升压力,发现性能瓶颈
- 使用线程:5,然后循环5000次,共2.5万个样本
- 使用线程:10,然后循环5000次,共5万个样本
- 使用线程:15,然后循环5000次,共7.5万个样本
- 使用线程:20,然后循环5000次,共10万个样本
- 使用线程:25,然后循环5000次,共12.5万个样本
- 使用线程:30,然后循环5000次,共15万个样本
- 使用线程:35,然后循环5000次,共17.5万个样本
- 使用线程:40,然后循环5000次,共20万个样本
聚合报告
Active Threads
RT
TPS
压测监控平台与JMeter压测结果一致
压测中服务器监控指标
2)问题1:网络到达瓶颈
注意:系统网络带宽上限(25Mbps)
结论:随着压力的上升,TPS不再增加,接口响应时间逐渐在增加,偶尔出现异常,瓶颈凸显。系统的
负载不高。CPU、内存正常,说明系统这部分资源利用率不高。带宽带宽显然已经触顶了。
优化方案:
- 方案01-降低接口响应数据包大小
- 返回数据量小的接口,响应数据包0.6kb,请求数据包0.421kb
http://ip:9001/spu/goods/10000023827800
方案02-提升带宽【或者在内网压测】
25Mbps –> 100Mbps
云服务器内网:这里在Linux中执行JMeter压测脚本
jmeter -n -t 02-jmeter-example.jmx -l 02-jmeter-example.jtl
优化之后:
方案01-降低接口响应数据包大小,压测结果
方案02-提升带宽【或者在内网压测】,压测结果
略
问题:可不可以基于RT与TPS算出服务端并发线程数?
服务端线程数计算公式:TPS/ (1000ms/ RT均值)
RT=21ms,TPS=800,服务端线程数:= 800/ (1000ms/ RT均值) = 17
RT=500ms,TPS=800,服务端线程数:= 800/ (1000ms/ RT均值) = 400
RT=1000ms,TPS=800,服务端线程数:= 800/ (1000ms/ RT均值) = 800
结论:
在低延时场景下,服务瓶颈主要在服务器带宽。
TPS数量等于服务端线程数 乘以 (1000ms/ RT均值)
RT=21ms,TPS=800,服务端线程数:= 800/ (1000ms/ RT均值) = 17
3)问题2:接口的响应时间是否正常?是不是所有的接口响应都可以这么快
情况02-模拟高延时场景,用户访问接口并发逐渐增加的过程。接口的响应时间为500ms,
- 线程梯度:100、200、300、400、500、600、700、800个线程;
- 循环请求次数200次
- 时间设置:Ramp-up period(inseconds)的值设为对应线程数的1/10;
- 测试总时长:约等于500ms x 200次 x 8 = 800s = 13分
- 配置断言:超过3s,响应状态码不为20000,则为无效请求
//慢接口
@GetMapping("/goods/slow/{spuId}")
public Result findGoodsBySpuIdTwo(@PathVariable String spuId){
Goods goods = spuService.findBySpuId(spuId);
//模拟慢接口
try {
//休眠500ms
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Result(true, StatusCode.OK, "查询成功", goods);
}
响应慢接口:500ms+,响应数据包3.8kb,请求数据包0.421k
http://ip:9001/spu/goods/slow/10000005620800
测试结果:RT、TPS、网络IO、CPU、内存、磁盘IO
结论:
- 在高延时场景下,服务瓶颈主要在容器最大并发线程数。
- RT=500ms,TPS=800,服务端线程数:= 800/ (1000ms/ RT) = 400
- Tomcat默认的最大的线程数?200
- 观察服务容器最大线程数,发现处理能力瓶颈卡在容器端
4)问题3:TPS在上升到一定的值之后,异常率较高
可以理解为与IO模型有关系,因为当前使用的是阻塞式IO模型。