您的位置 首页 > 数码极客

如何恢复closewait——如何恢复永久删除的照片

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自带的con (window)
  • jdk自带的jvi (window)
  • jstack(linux)
  • alibaba/arthas 阿里巴巴的插件,挺好用的,推荐使用,还可以反编译源码

首先查看cpu和内存

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

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

top -c

查看线程信息

linux

jstack java的进程id


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

jstack java的进程id >1.txt

然后在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命令

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引起的。我一个同事用redi()的到一个管道连接,然后在连接里面有for循环调用redi()方法,这样导致了redis连接池不够用。管道没释放。然后http请求都是用经过权限校验的,是shiro+redis做的。所有请求经过redis的时候就阻塞了。所有tomcat假死了。

总之tomcat假死大概就这些原因,还有需要注意点,有写批量操作,最好都用同个管道,不要每个都请求一个资源,这样会导致资源不够用,tcp都是close_wait状态。

改天介绍一下alibaba/arthas的这个插件怎么使用,真的非常方便

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“如何恢复closewait,如何恢复永久删除的照片,如何恢复删除的微信聊天记录,如何恢复手机删除的照片和视频,如何恢复近视”边界阅读