closewait过多原因_springboottomcat挂掉,假死⽆响应原因
总结和解决⽅案
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⾃带的 (window)
jdk⾃带的 (window)
jstack(linux)
springboot推荐算法alibaba/arthas 阿⾥巴巴的插件,挺好⽤的,推荐使⽤,还可以反编译源码⾸先查看cpu和内存
⽤jvisualvm(也可以远程连接到linux上⾯,改天我写个⽂章)
如果是linux系统的话,可以⽤top -c 查看cpu和内存
top -c
查看线程信息
linux
jstack java的进程id
如果要查看有没有线程死锁,你可以按照下⾯命令做
jstack java的进程id &
然后在1.txt⽂件查⼀下有没有DeadThread关键词。没有就是没死锁
jconsole⽐较简单
当cpu和内存剧增的时候,可以查看是哪⼏个线程引起的,定位到这个线程。查看线程名称,基本上可以定位到问题。top c
可看出PID为7149的java进程占⽤cpu最⾼,达到了98%
查看进程中最耗cpu的⼦线程
top -p 7149 -H
如下图:可看出PID为7166的线程占⽤cpu最⾼,达到了97.7%
将最耗cpu的线程id转换为16进制输出
printf "%x n" 7166
查询具体出现问题的代码位置
jstack 7149 | grep 1bfe -A 30
如下图:可看出是JVMLearnApplication类的第18⾏出现问题
我曾经遇到过⼀个坑,就是activemq的⼴播消息太多,然后程序⽤线程池消费,线程池线程数配置太⼩,消费速度跟不上,就会堆到线程池队列中排队,内存剧增,cpu最后也跟这剧增。导致tomcat挂掉。最后把线程池的线程数配置⼤点,后⾯就正常了。
案例3
当cpu和内存正常的时候,线程也没有死锁,tomcat也没有死掉,就是访问不了,全部访问状态502超时。这个是怎么回事呢。别急,下⾯介绍怎么解决。
当出现这种情况的时候,先去查⼀下tcp连接情况,
Docker容器中安装netstat命令,如果没有netstat命令
Docker容器中安装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]}'
如果出现⼤量的close_wait的状态。那表⽰tcp没有正确释放。
定位到是tcp问题了,那接下来怎么办呢
http请求进来,都是502超时响应,那就表⽰处理http请求的线程都阻塞了,查看具体哪⾏代码阻塞就⾏了。
查线程http-nio-28001-exec这个些线程的线程信息,dump下来,看具体是请求什么阻塞了。
如果是请求redis线程池资源阻塞了,那看⼀下redis资源为什么没释放,或者什么不够⽤了。查看⼀下最近代码都对redis进⾏什么操作。数据库和上传⽂件和httpclient请求没关闭掉 都是跟redis⼀样的道理。
我之前遇到的坑就是redis引起的。我⼀个同事⽤Connect()的到⼀个管道连接,
然后在连接⾥⾯有for循环调⽤()⽅法,这样导致了redis连接池不够⽤。管道没释放。然后http请求都是⽤经过权限校验的,是shiro+redis做的。所
有请求经过redis的时候就阻塞了。所有tomcat假死了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论