某个线上tomcat服务运行正常,但是运行一段时间后无响应,呈假死状态,重启后页面访问正常,但是持续不久后又无响应。
以下是排查思路:
1、查看log日志,排查并无报错信息。
2、排查是否为内存溢出导致,经查询后与内存无关。
3、查看服务器内存情况,显示内存充足。
4、netstat 命令查看网络情况,发现问题。
5、通过jstack -l 进程id >> jstack.log 查看进程所有线程状态
打开netstat命令发现服务器的连接有 大量的CLOSE_WAIT状态
顺便复习一下TCP三次握手和四次挥手的过程。
三次握手:
四次挥手:
由此可以推测出大量close_wait的现象,是由于某些情况下,客户端关闭了socket连接,但是服务端可能忙于读或者写,没有关闭连接,导致tomcat连接线程耗尽,服务呈现假死状态。
查看服务的 进程id ps -ef|grep <service>
执行jstack <pid> 命令 查看进程所有线程状态
分析线程状态发现有大量的RUNNABLE线程,且该线程指向同一个方法,查看项目代码发现该方法是去调用confluent服务接口获取kafka消息,因此怀疑问题出在confluent上
同样dump confluent的线程日志发现,存在死锁,因此可以初步判断是由于confluent服务死锁导致的
解决办法:
confluent采用开源框架,一般不去改动,而是从自身项目去排查优化。
查看项目代码发现一个消息查询接口做了很多事情,重复创建消费实例,优化接口实现,减少不必要的并发调用。