tomcat经常挂掉MySQL_tomcat 挂掉,假死无响应原因总结和解决方案

tomcat假死原因

以前遇到tomcat莫名奇妙的假死了,没有任何的响应,然后重启后又可以了,隔段时间又假死了。以前不懂的处理和排除原因,纠结的半死。无从入手,都想砸电脑,小伙伴们有遇到过,我遇到过4次。

其实tomcat假死引起的原因有很多,要具体分析一下和排查一下。

tomcat假死有以下几种可能的原因:

redis的连接池资源没释放掉(tcp没释放掉,tcp状态为close_wait)

数据库连接池资源没释放掉(tcp没释放掉,tcp状态为close_wait)

上传文件资源没关闭掉 (tcp没释放掉,tcp状态为close_wait)

httpclient请求没关闭掉 (tcp没释放掉,tcp状态为close_wait)

线程死锁

线程被阻塞了,没继续往下执行

tomcat的假死的原因有很多,很多是由于tcp没有释放掉。具体怎么排查原因,下面会介绍一下。

案例1

顺便说我遇到的一个坑,我曾经部署专门做定时任务项目,这个是用spring的quartz做的。发现定时任务执行一段时间后,居然没响应了,tomcat没挂掉,cpu和内存也正常。就是定时任务不执行。查看了线程,也没有死锁。后面查了很久,居然quartz的定时任务调度居然开启的是单线程的。由于我其中一个定时任务要执行消息写入数据库,这个量非常大,而且服务器配置比较差,写入比较慢。所以导致这个任务要执行差不多1天,导致其他定时任务不执行,所以还以为tomcat挂掉了。所以有时候要排查线程数是否足够。

案例2

当服务器挂掉的时候,查看一下日志看能不能查出问题。日志查看不出来的时候,查看运行时候cpu和内存的波动,如果cpu和内存波动很大,就去查看堆栈信息,看哪个线程占用的cpu和内存比较高。dump线程信息,查看一下具体代码哪个位置引起的。

查看堆栈信息可以使用以下工具

jdk自带的console.exe (window)

jdk自带的jvisualvm.exe (window)

jstack(linux)

alibaba/arthas 阿里巴巴的插件,挺好用的,推荐使用,还可以反编译源码

首先查看cpu和内存

用jvisualvm(也可以远程连接到linux上面,改天我写个文章)

786f774a1baebe3a157829486da5d1f0.png

如果是linux系统的话,可以用top -c 查看cpu和内存

top -c

735908240b54004d481b3052afc33743.png

查看线程信息

linux

jstack java的进程id

107d7d9c41d7c98a75d7fc3f69dda571.png

如果要查看有没有线程死锁,你可以按照下面命令做

jstack java的进程id >1.txt

然后在1.txt文件查找一下有没有DeadThread关键词。没有就是没死锁

jconsole比较简单

4f1f8da16e640d01bef6be51d0eb1dde.png

当cpu和内存剧增的时候,可以查看是哪几个线程引起的,定位到这个线程。查看线程名称,基本上可以定位到问题。

top c

可看出PID为7149的java进程占用cpu最高,达到了98%

36dbde8f3e9542158f2f3ab68c88fe26.png

查看进程中最耗cpu的子线程

top -p 7149 -H

如下图:可看出PID为7166的线程占用cpu最高,达到了97.7%

5eb78b7705b52cb526ff8844e8d8f8eb.png

将最耗cpu的线程id转换为16进制输出

printf "%x \n" 7166

bbe3e44a5968d66576e0c2a257aaced1.png

查询具体出现问题的代码位置

jstack 7149 | grep 1bfe -A 30

如下图:可看出是JVMLearnApplication类的第18行出现问题

a26a7c4c18b84a46e29d3d0cb681ef48.png

我曾经遇到过一个坑,就是activemq的广播消息太多,然后程序用线程池消费,线程池线程数配置太小,消费速度跟不上,就会堆到线程池队列中排队,内存剧增,cpu最后也跟这剧增。导致tomcat挂掉。最后把线程池的线程数配置大点,后面就正常了。

案例3

当cpu和内存正常的时候,线程也没有死锁,tomcat也没有死掉,就是访问不了,全部访问状态502超时。这个是怎么回事呢。别急,下面介绍怎么解决。

当出现这种情况的时候,先去查一下tcp连接情况,

Docker容器中安装netstat命令,如果没有netstat命令

apt-get update

apt-get install net-tools

linux查看方式如下:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

a580b76f6cd5b662a65d77fcff701de0.png

如果出现大量的close_wait的状态。那表示tcp没有正确释放。

定位到是tcp问题了,那接下来怎么办呢

http请求进来,都是502超时响应,那就表示处理http请求的线程都阻塞了,查看具体哪行代码阻塞就行了。

查找线程http-nio-28001-exec这个些线程的线程信息,dump下来,看具体是请求什么阻塞了。

8548729b4202bcc53069a7fa4ebc44b9.png

如果是请求redis线程池资源阻塞了,那看一下redis资源为什么没释放,或者什么不够用了。查看一下最近代码都对redis进行什么操作。

数据库和上传文件和httpclient请求没关闭掉 都是跟redis一样的道理。

我之前遇到的坑就是redis引起的。我一个同事用redisTemplate.getConnect()的到一个管道连接,然后在连接里面有for循环调用redisTempate.get()方法,这样导致了redis连接池不够用。管道没释放。然后http请求都是用经过权限校验的,是shiro+redis做的。所有请求经过redis的时候就阻塞了。所有tomcat假死了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

CharlesDDDD

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值