当前位置: 首页 > Linux

数据库连接池连接耗尽,导致tomcat请求无响应,呈现假死状态

时间:2023-04-06 02:24:01 Linux

最难的是认识自己!个人网站,欢迎访问!前言:最近测试部的同事来找我说,他们在测试的时候,发现服务接口请求有一段时间没有响应了。Tomcat好像死了,并没有返回任何错误响应。让我快速检查一下;我一听,瞬间惊呆了,姐姐,最近总是出问题,领导要给我开批评会。哈哈,开玩笑的,我这么帅的人,领导怎么忍心批评我,哼哼,我马上解决这个问题,不让领导知道!简单说一下程序部署:tomcat+oracle排查过程:排查时可以使用命令排查,也可以使用可视化监控工具;例如使用JDK自带的jvisualvm.exe监控工具。命令故障处理过程:1.请求的服务无响应。首先查看tomcat是否真的宕机:命令:ps-ef|greptomcat通过以上命令查看tomcat是否正在运行;执行结果如下:注意:如果服务器正在运行如果有多个tomcat在运行,需要检查下图框内运行的tomcat的地址是否正确;通过命令检查,发现tomcat运行正常,那么这个就处于假死状态,接下来就是检查了。2、查看http请求是否到达tomcat:查看tomcat的logs目录下localhost_access_log日志文件中的请求记录;command:tail-100flocalhost_access_log通过上面的命令查看实时日志,执行上面的命令查看日志后,再请求程序,在日志中没有发现请求记录,说明tomcat处于状态假死了,下一步就是检查了。3、查看tomcat的JVM的GC状态:查看GC状态,是否因为频繁GC或者长时间GC导致程序长时间卡顿,最终请求来不及处理,而它进入队列等待,调用者长时间无响应,导致tomcat假死;命令:jstat-gcpidtimecount例如:jstat-gc7112910005监控71129进程的JVMGC状态,每1000ms输出一次,共输出5次;命令执行结果参数分析:通过上述命令查看GC情况,发现垃圾回收不频繁,GC时间不长,应该不是GC的原因。4、查看tomcat的JVM堆状态:查看堆内存状态,是否存在堆内存溢出导致tomcat卡死,无法为新的请求分配堆内存资源;命令:jmap-heappid例子:jmap-heap7112971129正在运行的tomcat进程号;从命令执行结果来看,堆内存中可用内存还是很大的,不会出现内存溢出问题,所以不是堆内存小导致的tomcat假死。5、查看tomcat的JVM线程状态:①使用jstack命令导出当前JVM的threaddump快照,然后查看dump中的线程在做什么?命令:jstackpid>>jvmThreadDump.log示例:jstack71129>>jvmThreadDump.log生成71129进程的JVM线程快照,并将快照内容重定向到jvmThreadDump.log文件;注意:生成的jvmThreadDump.log在你当前执行命令的目录中。②、然后使用命令more查看jvmThreadDump.log的内容;command:morejvmThreadDump.log如果dump文件太大,需要使用more命令稍微查看一下;执行more命令后,按回车键显示文件内容;③.通过查看线程快照文件,发现很多线程的状态都是WAITING;并使用命令查看线程状态为WAITING的线程占总线程的比例:注意:tomcatDump.log是生成的线程快照文件的名字,记得改成自己设置的名字;计数=`cattomcatDump.log|grepjava.lang.线程状态|wc-l`;等待=`cattomcatDump.log|正在等待|wc-l`;一个=`回声|awk"{print$wait/$count*100}"`;echo"$a%"执行命令,结果为:91.9786%,发现90%以上的线程处于等待状态;至此,tomcat假死的原因找到了,但还需要进一步确定是什么原因导致大量线程等待?通过查看调用的服务接口的代码,我知道我在这个接口的业务逻辑上没有设置任何锁,所以我写的代码应该没有问题,但是这个接口涉及到很多JDBC数据库操作.它在数据库连接池中吗?连接不够?因为数据库连接是竞争资源,如果连接池中的连接已经用完,那么下一个JDBC线程就需要等待连接。6、查看与数据库建立的TCP连接:上面发现有大量线程处于等待状态,但通过分析,可能是数据库连接池中的连接耗尽导致的,可以查看通过命令部署服务,代码服务器与数据库所在服务器建立的TCP连接数是否达到配置的数据库连接池中的最大连接数;命令:netstat-pan|grep1521|wc-l因为本文使用的数据库是Oracle,所以grep搜索匹配的端口号是1521;如果是mysql数据库,把端口号改成3306,netstat-pan|grep3306|wc-l;如果设置了自定义数据库端口号,将其更改为自定义端口号即可;通过命令查询,已经使用的数据库连接数为6,然后查看数据库连接池集合中的最大连接数;数据源配置如下:通过查看数据源发现连接配置的最大连接数poolismaxActive="6";发现当前程序使用的连接数已经达到最大值,则后面执行JDBC操作的线程会进入等待状态,等待获取连接;至此,tomcat假死的排查过程就结束了,也找到了原因,就是数据库连接池中的连接耗尽了;所以在后面的测试中,需要在数据源中设置最大连接数变大,再进一步查看代码,看有没有使用后没有关闭的数据库连接除了数据库连接池连接耗尽导致tomcat假死的问题外,还有一些其他情况可能导致它发生的原因,例如:redis连接池连接耗尽,或者redis连接使用后没有释放,最终导致redis连接耗尽。除了使用上面的命令排查外,还可以直接使用可视化监控工具进行故障排除,更加方便直观。可视化监控工具排查使用JDK自带的jvisualvm.exe工具对tomcat进行JMX远程可视化监控;jvisualvm.exe位于$JAVA_HOME/bin目录下;一、使用JMX实现远程监控步骤:下面使用JMX实现远程监控。:jvisualvm远程监控tomcat①、在Tomcat的bin目录下的startup.sh文件的倒数第二行添加如下内容:exportCATALINA_OPTS="$CATALINA_OPTS-Dcom.sun.management.jmxremote-Djava.rmi.server.hostname=192.168.1.130-Dcom.sun.management.jmxremote.port=7003-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false"注:如果直接复制以上内容,然后放到startup.sh文件中,tomcat可能会因为空格多而启动失败;请复制以下内容并修改:exportCATALINA_OPTS="$CATALINA_OPTS-Dcom.sun.management.jmxremote-Djava.rmi.server.hostname=192.168.1.130-Dcom.sun.management.jmxremote.port=7003-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false》以上参数解析:-Dcom.sun.management.jmxremote启用JMX远程监控-Djava.rmi.server.hostname=192.168.1.130这是你tomcat连接的服务器地址-Dcom.sun.management.jmxremote.port=7003jmx连接端口-Dcom.sun.management.jmxremote.ssl=false是否ssl加密-Dcom.sun.management.jmxremote.authenticate=false远程连接需要密码认证在startup.sh文件中添加以上内容后,需要重启tomcat才能生效;②、打开jvisualvm.exe,界面如下:③.远程右键,添加主机,输入服务器的ip:即在startup.sh文件中的内容中添加主机名④。在远程主机上右击,添加JMX连接,在ip地址后面手动添加上面设置jmx连接端口7003,然后点击确定:⑤.通过以上步骤,远程监控连接已经完成,然后双击启动监控界面:2、查看监控内容:通过查看监控画面得知CPU、GC、Heap都没有问题,然后查看线程状态:点击上图中的threaddump按钮,生成线程快照。快照文件内容如下:通过查看快照文件内容,发现很多线程的状态都处于等待状态;接下来的分析排查过程和上面的命令排查过程是一样的不会让你修改配置文件进行远程监控,即使使用监控工具看起来更直观方便;因此,您需要记住一些常用的故障排除命令,以备不时之需。由于本人水平有限,如有疑问请追问;?别忘了留下你的学习足迹【点赞+收藏+评论】嘿嘿ヾ看文章不点赞的都是“流氓”,嘿嘿ヾ(?°?°?)??!开玩笑,动动小手,点个赞,就完事了。你们每个人都做出贡献(喜欢+评论),更多的学习者将加入!太感谢了! ̄ω ̄=