一、怎么确定系统到达了性能瓶颈
1、吞吐量不再随着并发量增加而增加
2、吞吐量下降
3、程序性能指标不达标,包括吞吐量、响应时间、错误率、资源占用率
二、排查思路
分层思路:
(1)先客户端再服务端
(2)先硬件资源再应用程序
(3)JAVA应用程序:JVM虚拟机层、WEB服务器层、代码层面
1、客户端
客户端出现瓶颈现象
加大线程数量,请求数不再增加
排查方向
网络带宽、端口占用情况、CPU使用率、内存使用率、磁盘使用率
优化方法
1、硬件资源不足:增加单机的硬件资源配置
2、单机硬件硬件配置没有优化空间:考虑集群,比如jmeter集群
2、服务端
2.1 网络瓶颈
到达网络瓶颈现象:
网络带宽占满??请求数增加的情况下,服务器其他资源使用率不高,网络使用率很高
排查方法:
iperf3: 检测网络速度工具
iftop监控工具:查看每个 某个ip的某个端口号网络使用情况,比如:接收流量、发送流量、总流量、流量峰值、平均流量等
尝试增加网络带宽,查看吞吐量是否增加,如果有增加,说明是网络到达瓶颈,限制了系统性能的提升
优化方法:
1、增加网络带宽
2、减少数据传输量:比如压缩传输,比如减少不必要的数据传输
2.2 磁盘瓶颈
到达磁盘瓶颈现象:
1、请求数增加的情况下,服务器其他资源使用率不高,磁盘使用率很高,比如90%以上
2、请求数增加的情况下,服务器其他资源使用率不高,磁盘使用率也不高,可能是磁盘故障了,比如部分不可用,或者磁盘本身的IO性能低,读写速度慢,遇到有大量文件处理,比如图片存储、大量日志、安装了数据库软件等情况,处理速度低,影响整体的性能
排查方法:
df:磁盘使用情况
dd:粗略估计磁盘IO性能(读写速度),对磁盘的损害较大,不建议多次测试
iotop监控工具:监控磁盘I/O使用情况
优化方法:
1、增加磁盘大小
2、更换读写速度快的磁盘
3、减少数据量:
压缩图片控制日志的详细程序,比如生产环境,只输入warn/error的日志,开发测试环境输出info/debug类型的日志
减少mysql中存储的数据量,比如分库分表??
2.3、CPU瓶颈
到达CPU瓶颈现象:
1、吞吐量达到了瓶颈(增加请求,吞吐量不再增加,甚至下降),CPU使用率过高(超过90%、95%,甚至接近100%),其他资源使用率不高
2、并非量不高,但是CPU使用率很高——很可能有代码问题
排查方法:
排查CPU占用高的代码段,检查代码书写是否有问题,是否可以优化
优化方法:
1、增加CPU配置,比如增加CPU核数
2、优化程序
2.4 内存瓶颈
到达内存瓶颈现象:
1、吞吐量达到了瓶颈(增加请求,吞吐量不再增加,甚至下降),内存资源占用过高(超过90%、95%,甚至接近100%),其他资源占用率不高
2、并非量不高,但是内存使用率很高——很可能有内存泄漏
可能的原因:
1、缓存问题: 缓存使用不当,导致缓存数据过多占用内存。
2、应用程序内存泄漏:应用程序没有正确释放内存,导致内存泄漏。
3、内存不够
监控方法:
1、top、htop、free :监控命令
2、promthus+grafana:监控大盘
验证方法:
1、使用内存分析工具,比如MAT,查看是否有内存泄漏——修复内存泄漏后,查看内存使用率是否降低
2、优化缓存策略,设置合理的缓存过期时间,定期清理不再使用的缓存——查看内存使用率是否降低
3、如果代码没有排查出问题,增加内存配置——查看内存使用率是否降低
2.5、web容器配置瓶颈——线程数配置过少
现象:吞吐量到达瓶颈了,cpu使用率不高(<80%)
可疑原因:
程序配置的线程数太少,没有榨干服务器硬件资源。
或者是测试场景中的并发量不够
验证方法:
1. 加大并发 -- 排查性能测试并发不够的问题
2. 增加线程池大小- 增加之后,性能是否有提升修改线程数配置方法:
springboot
-Dserver.tomcat.max-threads=100
最多线程数
默认 200
-Dserver.tomcat.min-spare-threads=100
最少线程数
默认 10
-Dserver.tomcat.max-connections=100
总链接数量
默认 10000
-Dserver.tomcat.accept-count=100
网络堆积数量
默认100tomcat
server.xml文件里面配置
minSpareThreads
maxThreads
acceptCount
操作系统可能会忽略此设置,并对队列使用不同的大小
maxConnections
操作系统可能仍会根据设置接受连接核心参数的作用
理论上 tomcat 能够同时接收的连接 = acceptCount + MaxConnections
线程数量 决定的是 tomcat 同时处理的请求数量,只有及时处理请求才能提高 吞吐量才能加快响应时间。推荐修改 线程的配置,其他配置未必生效,相见:Apache Tomcat 9 Configuration Reference (9.0.86) - The HTTP Connector
2.6、JVM配置瓶颈——JVM内存配置过低
现象:吞吐量到达瓶颈了,内存使用率不高(<80%),JVM内存使用率很高(甚至出现了OutOfMemoryError或者StackOverflowError错误)
可疑原因:1、内存配置太小,没有榨干服务器内存资源。
2、应用代码问题——存在内存泄漏、不合理的递归程序
监控方法:
jmap、jconsole、jVisualVm、prometheus + grafana(程序启动时配置代理参数:-javaagent:/u01/monitor/jmx_prometheus_javaagent-0.17.0.jar=12346:/u01/monitor/jmx_springboot.yaml)
优化方法:
StackOverflowError错误
1、递归会引起占用大量内存,确认代码中的递归合理性
2、如果确实有大量递归,需要很大栈内存,调整栈内存参数:-Xss
备注:增加这个值,线程数就少了
OutOfMemoryError
java.lang.OutOfMemoryError: Metaspace1.8+ java.lang.OutOfMemoryError: PermGen space:元数据空间内存不够,可以尝试加大元数据内存空间:-XX:MaxPermSize=512m
java.lang.OutOfMemoryError: Java heap spacejava.lang.OutOfMemoryError:GC overhead limit exceeded:堆内存不够,加大堆内存:-Xmx512m,或者分析内存占用是否合理,使用MAT(eclipseMemory Analyzer Tools)工具分析内存快找
修改JVM内存配置方法:
-Xms:堆内存最小值,例如:-Xms4g
-Xmx:堆内存最大值
java原生命令(springboot):java -Xmx2G -jar xxx.jar
Tomcat配置:
windows 写在 bin 目录 setenv.bat
linux 写在 bin 目录 setenv.sh
2.7、 JVM GC配置调优
现象:吞吐量成波浪状
目的:期望优化吞吐量稳定性(波浪变小)、或者期望缩短平均响应时间
疑因分析:
JVM 垃圾回收 导致STW(stop the world),产生时间停顿(一个请求的时间 +=处理时间业务代码 执行时间 + GC垃圾回收时间)
波浪小:可能是小规模GC 比较多,或者每次GC时间不长,能接受就行
波浪起伏大:GC时间长,可能是产生了多次fullgc,调整垃圾回收器参数,减少停顿时间优化思路:
并发量没有减少,垃圾不会减少;可以通过提升GC次数,降低每次垃圾回收的时间,从而减少请求时间
优化方法:调整GC参数配置
自适应参数
1. 单次最大暂停时间(STW时间)-XX:MaxGCPauseMillis=
JVM尽量保障把每次GC的时间控制在这个时间内
2. 应用程序吞吐量目标-XX:GCTimeRatio=19
如果参数设置为19,则垃圾回收总时间小于应用程序总运行时间的5%。计算公式: GC总时长限值 = 1/(1+GCTimeRatio) * 程序总时长
这两个参数配置后,JVM会根据运行情况,自动动态调整堆中分代各区域的大小。 在这种动态调整的情况下,JVM自行选择。同时配置,优先保证的顺序:最大暂停时间目标 > 吞吐量目标切换不同的垃圾回收器这个是用的最多的GC方面优化手段
-XX:+UseParallelGC -XX:+UseParallelOldGC
大部分默认这种
-XX:+UseConcMarkSweepGC
响应时间要求高的选择这一种
G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC
大内存服务器选择这一种备注:最后优化JVM GC参数,优化空间有限