排查压测问题引发的系统性能调优过程

本文详细记录了在面临压力测试时,系统吞吐量无法提升及服务器资源利用率低的问题,如何逐步排查Tomcat连接器、JVM参数、线程堆栈、数据库连接池以及Linux服务器参数等,最终定位到Redis连接池配置不合理导致的问题,并通过调优提高性能的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上图中的接口项目、Redis、MySql 都是单机安装部署的 。

注意:在进行下文之前,我们还需要记住一个前提:本项目中的接口代码是不存在问题的,并且数据库查询SQL都是最优的,都是走索引查询的,本次压力测试问题不是由于代码导致的,而是由于各种参数未调优造成的;代码调优和SQL调优在编码阶段就已经完成了。

简单性能调优的点:

=========

在上文中的项目部署情况和测试脚本的配置情况下进行压力测试时,就出现了小梦说的系统吞吐量上不去,以及应用服务器(部署接口项目的服务器)的 CPU 等资源使用率都很低的情况;

查看 JMeter 测试时系统的吞吐量如下图:

=======================

排查压测问题引发的系统性能调优过程

查看应用服务器(部署接口项目的服务器)的CPU使用率很低:

=============================

排查压测问题引发的系统性能调优过程

按照测试脚本的50个并发以及接口中含有计算密集型操作(加解密和验签)的情况,CPU是不应该这么低的;哎!什么鬼嘛?

排查压测问题引发的系统性能调优过程

别急,下面我们就展开具体的排查过程,并在排查过程中逐步了解各个调优的点;

排查过程就是按照文章开头中的 本文主线 图片中 简单性能调优的点 展开的 。

排查Tomcat连接器参数配置:

================

Tomcat 连接器参数配置只需要考虑以下几个方面:

==========================

  • Connector使用哪种 protocol 协议HTTP/1.1:默认值,使用的协议与Tomcat版本有关建议使用 NIO2 :org.apache.coyote.http11.Http11Nio2Protocol除了NIO2协议外,还有 BIO、NIO、APR 协议,可以自行去查阅资料;

  • acceptCount:等待队列的长度;当等待队列中连接的个数达到acceptCount时,说明队列已满,再进来的请求一律被拒绝;默认值是100。

  • maxConnections:Tomcat 在任意时刻接收和处理的最大连接数;当连接数达到最大值maxConnections后,Tomcat会继续接收连接,直到accept等待队列填满。如果最大连接数设置为-1,则表示禁用maxconnections功能,表示不限制tomcat容器的连接数;最大连接数默认值与连接器使用的 protocol 协议有关:NIO的默认值是10000;APR/native的默认值是8192;BIO的默认值为maxThreads(如果配置了Executor,则默认值是Executor的maxThreads);

  • maxThreads:每一次HTTP请求到达 Tomcat,都会创建一个线程来处理该请求,那么最大线程数决定了Tomcat 可以同时处理多少个请求。maxThreads 默认200;建议:maxThreads应该设置大些,以便能够充分利用CPU;当然,也不是越大越好,如果maxThreads过大,那么CPU会花费大量的时间用于线程的上下文切换,整体效率可能会降低;这需要根据自己项目的情况和服务器硬件配置情况配置合适的值即可;

下面就是本次压测时配置的Tomcat连接器参数:

========================

<Connector

port=“8080”

protocol=“org.apache.coyote.http11.Http11Nio2Protocol”

maxThreads=“1000”

maxConnections=“2000”

acceptCount=“1000”

connectionTimeout=“20000”

redirectPort=“8443”

enableLookups=“false”

maxPostSize=“10485760”

compression=“on”

disableUploadTimeout=“true”

compressionMinSize=“2048”

acceptorThreadCount=“2”

compressableMimeType=“text/html,text/xml,text/css,text/javascript”

URIEncoding=“utf-8” />

上面连接器中配置参数:的

  • 连接器使用的 protocol 协议是 NIO2

  • 最大线程数 maxThreads=“1000”

  • 最大连接数 maxConnections=“2000”

  • 等待队列大小 acceptCount=“1000”

根据上面连接器配置参数,和压测脚本配置的并发请求才50个,确定压测问题应该不是由于连接器参数造成的。

其实在查看Tomcat配置文件 server.xml 中的连接器参数前,可以使用下面这个命令先直接统计出 JMeter与Tomcat建立的Http连接数: 注意 8080 指的是 Tomcat 端口号,使用前改成你的Tomcat配置的端口

netstat -pan | grep 8080 | wc -l

如果统计出的连接数与测试脚本中配置的并发数的话差不多一致的话,说明当前连接器是可以满足连接请求处理的,初步可以判断不是由于连接器参数造成的本次压测问题;然后再可以去查看配置文件中的参数进行确认下。

排查压测问题引发的系统性能调优过程

排查 JVM 参数配置:

============

注意:JVM 参数配置比较复杂,这块的参数调优需要根据具体项目情况、服务器硬件配置等进行合理配置。

查看当前压测的接口项目 JVM 配置参数:

=====================

  • 直接使用命令查看:ps -ef | grep tomcat结果如下:

  • 也可以直接去 catalina.sh 配置文件中查看:JAVA_OPTS=" -server -Xms6000m -Xmx6000m "

  • 也可以直接通过 jmap 命令查看 JVM 的堆的配置信息:注意:下面命令中的129761 是tomcat的 pid 进程号;jmap -heap 129761结果如下:

看到这,应该会有人问,为什么你的初始堆大小和最大堆大小(-Xms6000m -Xmx6000m)设置为一样呢?

因为如果虚拟机启动时设置的初始堆内存比较小,这个时候又需要初始化很多对象数据,那么虚拟机就必须不断地扩大堆内存,这样也会产生一些消耗的。

排查下是否由于JVM参数配置的不合理导致:

=====================

  • 使用上面提到的 jmap 命令查看下当前堆内存的使用情况jmap -heap 129761

通过查看上面的堆内存的使用情况,发现还有很多空间使用呢,应该不是由于JVM参数不合理导致的压测问题;

但是咱别着急,咱再查看下JVM中垃圾回收GC的情况;

  • 使用命令 jstat 查看垃圾回收GC的情况:注意:129761 为Tocamt的pid; 1000 表示间隔时间毫秒,10 表示输出10次GC情况jstat -gc 129761 1000 10

看了上面的GC情况,发现垃圾回收也没什么异常,FGC总共就3次,通过查看的堆使用情况和GC垃圾回收的情况可以确认压测的问题不是由于JVM的参数导致的。

看来这次压测的问题挺棘手呀,到现在还没有确认出问题原因呢!难道我这bug绝缘体质由于今天吃的比较多 ,导致失效了吗? 皱眉 ing . . . . .

排查压测问题引发的系统性能调优过程

看来还得接着排查,咱直接导出当前接口服务应用进程的 线程堆栈信息 看看吧。

  • 使用命令jstack导出线程栈信息:注意:129761 为Tomcat 的pid, /usr/local/test.log 未生成的线程堆栈文件 test.log 的存放地址jstack 129761 >>/usr/local/test.log

  • 导出线程堆栈信息后,使用命令搜索出状态为 WAITING 的线程;注意:找 State 为WAITING 状态的线程;命令如下:test.log 文件为刚刚导出的 线程堆栈信息文件cat test.log | grep -n20 " WAITING "在命令执行后的搜索结果中发现了下图内容:

除了线程状态为 WAITING 的之外,还特别要注意 WAITING 状态线程的方法调用栈中存在项目业务代码的;

  • 上面图片中就展示了线程状态为 WAITING 等待的调用方法栈中有业务代码;

  • 业务代码是去Redis中查询数据,上图中第二个圈中的内容就是业务代码,并且这行代码上方是去Redis连接池中获取连接,由此确定是由于Redis连接获取不到,导致线程处于 WAITING 等待状态;

  • 由于接口服务系统中很多线程获取不到Redis连接导致阻塞,从而无法充分利用CPU;所以在压测时,服务器CPU的使用率也压不上去,CPU的使用率很低;

至此,终于排查出了一处问题地方,不容易呀,感觉排查问题比写代码困难多了!

排查压测问题引发的系统性能调优过程

上面通过线程的堆栈信息排查出 Redis 连接不够用,应该是 Redis 连接池中的最大连接数配置的比较小,那接下来就确定下连接池的配置数据。

排查连接池参数配置:

==========

上文中,在线程的堆栈信息中排查出存在很多线程由于获取不到Redis连接导致处于等待阻塞状态;

接下来,咱们就来具体统计下现在处于压测中的应用服务器(部署接口项目的服务器)与Redis建立的连接数,顺带一起再排查下项目中使用的MySql 的连接池配置是否也存在问题?

  • 使用命令查看当前压测中的应用服务器与Redis建立的连接数注意:6379 为 redis的端口号netstat -pan | grep 6379 | wc -l执行命令查询出与Redis建立的连接数为 10,这在测试脚本50个并发请求下是一定不够用的呀,应该是配置的Redis连接池的最大连接数比较小;然后通过看接口代码中的配置文件发现,确实Redis连接池中的最大连接数配置是 10 个;最后修改了最大连接数为 300 个;注意:这个最大连接数需要根据项目情况和测试计划来设置,不用设置的太大。

  • 接着,使用命令顺带统计下当前处于压测中的应用服务器(部署接口项目的服务器)与MySql 建立的连接数注意:3306 为MySql 的端口号netstat -pan | grep 3306 | wc -l执行命令发现已经建立的MySql 连接数是 50,然后通过查看配置文件的连接池中最大的连接数为100,发现还没有达到最大连接数,说明 JDBC 连接够用,本次压测问题不是由于JDBC连接不够用导致的;并且在上文中查看线程的堆栈信息时,也没有发现调用 JDBC 操作的线程处于 WAITING 等待状态。

排查完了数据库连接池了,咱们就再排查下MySql 数据库是否进行了参数调优;

如果MySql 数据库没有进行调优的话,那在压测时就会出现数据库的读写性能比较差,也就是项目中在进行 JDBC 增删改查操作时会比较慢,进而导致存在JDBC操作的线程执行慢,无法充分利用CPU的并发计算能力,所以也会导致应用服务器的CPU使用率比较低,最终压测时整个接口应用系统的吞吐量也很低 。

排查压测问题引发的系统性能调优过程

排查MySql 数据库调优配置:

================

排查前先聊一个由于之前MySql 数据库未进行优化,而导致的压测问题。

MySql 数据库未调优,引发的压测问题 简述:

========================

之前压测时的场景还原:

在压测前所有该调优的地方都调了,就单独忘记对MySql 数据库进行调优了,最终导致对应用压测时,发现应用服务器(部署接口项目的服务器)的CPU的使用率一直浮动在60%左右,始终压不上去,即使加大压测时的并发请求数,发现还是不行;

最终通过查看MySql 服务器的磁盘IO的情况和MySql 数据库进程的CPU、内存等使用率发现MySql 没有被优化,所以导致MySql 数据库的读写能力被限制,进而导致应用并发处理能力下降,从而导致应用服务器的CPU使用率一直升不上去。

  • 使用命令统计下压测时 MySql 数据库所部署在的服务器的磁盘IO性能:注意: 1 指的是 间隔时间1秒, 5 指的是统计5次 IO 的情况;iostat -xdk 1 5

结果如下:

排查压测问题引发的系统性能调优过程

只需要注意图中圈起来的地方;await 指的是 磁盘读写时的等待时间,这个值越小越好;%util 指的是磁盘整体的负载情况,值越大说明磁盘负载快达到极限了。

  • 使用命令查看MySql 进程的CPU、内存的使用率:注意: 14208 是MySql 的pid;top -p 14208结果如图:

注意:

当时就是通过这两条命令统计出的数据,发现数据库服务器磁盘IO的负载一直处于90%,快达到极限了;但是MySql 进程的CPU、内存的使用率却很低;

通过这两条数据可以初步确定MySql 没有进行优化;如果MySql 进行了调优,那么MySql 的进程在压测时的CPU、内存等使用率不可能这么低,并且磁盘 IO 的负载也不会达到了极限;

得出初步结论后,然后去查看MySql 数据库的配置文件 my.cnf, 发现确实没有进行一些参数的优化,只是简单配置了最大连接数为 500;注意,MySql 数据库默认的最大连接数是 100 个;

最后在 my.cnf 配置文件中简单配置了下 innodb 存储引擎缓冲池大小 等;这里就不具体描述调优的参数了,因为调优参数都是需要根据项目情况、服务器硬件配置等综合考虑配置的;大家可以自行网上查阅MySql 数据库调优的相关资料;

配置好后,重启了MySql 数据库,然后重新进行压测,发现应用服务器(部署接口项目的服务器)的CPU使用率上去了,MySql 数据库进程的CPU、内存等使用率也升上去了,并且磁盘IO的负载也降下来了,最后整个应用系统的吞吐量也上去了,也支持更大的并发数了。

说完了上面之前遇到的一个压测小场景,咱们接着按照上面的排查步骤排查这次压测的问题,发现MySql 数据库已经进行了调优,磁盘IO的读写速度也是OK的,所以说本次压测问题与MySql 数据库参数配置无关。

排查完了MySql 数据库后,咱接着排查下Linux服务器的参数是否进行过调优吧!

排查压测问题引发的系统性能调优过程

排查Linux服务器参数配置:

===============

服务器参数调优这块目前了解的不多,只知道配置下服务器的 文件句柄数 fd ;建议将服务器的文件句柄数设置的大些;为什么设置大些呢?

因为主流操作系统的设计是将 TCP/UDP 连接采用与文件一样的方式去管理, 即一个连接对应于一个文件描述符(文件句柄) ;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后我们该如何学习?

1、看视频进行系统学习

这几年的Crud经历,让我明白自己真的算是菜鸡中的战斗机,也正因为Crud,导致自己技术比较零散,也不够深入不够系统,所以重新进行学习是很有必要的。我差的是系统知识,差的结构框架和思路,所以通过视频来学习,效果更好,也更全面。关于视频学习,个人可以推荐去B站进行学习,B站上有很多学习视频,唯一的缺点就是免费的容易过时。

另外,我自己也珍藏了好几套视频资料躺在网盘里,有需要的我也可以分享给你:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

2、读源码,看实战笔记,学习大神思路

“编程语言是程序员的表达的方式,而架构是程序员对世界的认知”。所以,程序员要想快速认知并学习架构,读源码是必不可少的。阅读源码,是解决问题 + 理解事物,更重要的:看到源码背后的想法;程序员说:读万行源码,行万种实践。

Spring源码深度解析:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

Mybatis 3源码深度解析:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

Redis学习笔记:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

Spring Boot核心技术-笔记:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

3、面试前夕,刷题冲刺

面试的前一周时间内,就可以开始刷题冲刺了。请记住,刷题的时候,技术的优先,算法的看些基本的,比如排序等即可,而智力题,除非是校招,否则一般不怎么会问。

关于面试刷题,我个人也准备了一套系统的面试题,帮助你举一反三:

1年半经验,2本学历,Curd背景,竟给30K,我的美团Offer终于来了

只有技术过硬,在哪儿都不愁就业,“万般带不去,唯有业随身”学习本来就不是在课堂那几年说了算,而是在人生的旅途中不间断的事情。

人生短暂,别稀里糊涂的活一辈子,不要将就。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
Spring Boot核心技术-笔记:

[外链图片转存中…(img-JCbRz83G-1713704338950)]

3、面试前夕,刷题冲刺

面试的前一周时间内,就可以开始刷题冲刺了。请记住,刷题的时候,技术的优先,算法的看些基本的,比如排序等即可,而智力题,除非是校招,否则一般不怎么会问。

关于面试刷题,我个人也准备了一套系统的面试题,帮助你举一反三:

[外链图片转存中…(img-Bdv0FIee-1713704338950)]

只有技术过硬,在哪儿都不愁就业,“万般带不去,唯有业随身”学习本来就不是在课堂那几年说了算,而是在人生的旅途中不间断的事情。

人生短暂,别稀里糊涂的活一辈子,不要将就。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值