问题描述:
项目某个模块的接口无法使用
问题排查:
-
查看运行日志,未发现相关接口的异常信息。
-
打印gc日志,对gc日志进行分析,未发现频繁GC的日志信息。
-XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/home/gc.log
- 查看服务器的cpu占用情况,CPU占用的并不高。,排除内存溢出的情况。
top -H -p 进程号
- 查看TCP连接状况,发现大量的TCP连接处于CLOSE_WAIT状态。
netstat -anop --tcp -p 进程号
- 进一步使用jstack工具对于进程进行分析。
jstack -l 进程号 >> /home/stack.log
stack日志分析:
- 查看具体wait线程的堆栈信息,定位具体方法。
- 如果上述步骤无法定位的具体方法,则向下追溯线程ID,直到找到对应的线程堆栈信息,发现两个问题。
问题一,初步判断,行锁问题。
上述图片说明,线程100处于等待状态,继续向下追溯,
一直到线程97,线程处于运行状态,但是未获取到数据库的锁,由于该堆栈的方法定位是数据库操作,初步判断可能未在同一事务下同时进行插入和更新操作,导致行锁。
问题二,初步判断,RestTemplate未设置超时时间。
猜测网络阻塞情况下,未设置超时时间,长时间获取输入流,导致程序僵死,无法继续执行下去。
解决措施:
- 优化相关业务代码。
- 添加Rest配置。
后续:
如上述措施无法解决该问题,则需要bug复现,然后使用tcpdump进行抓包分析,使用Wireshark分析tomcat和nginx之间的数据包内容,定位到具体的一次tcp连接导致服务器未响应FIN_WAIT_2,导致CLOSE_WAIT。
- tcpdump使用,监测网卡和端口,生成cap文件。
tcpdump -i eno16780032 -e tcp port 8080 -w target.cap -w target.cap
- Wireshark使用,下载cap文件,导入,分析数据包。
相关博客参考
- TCP通讯流程
https://blog.csdn.net/m0_38121874/article/details/81990457
- TCP协议详解
https://blog.csdn.net/qq_37884273/article/details/82188586
- jstack中pid状态解释
https://blog.csdn.net/dongyansheng_max/article/details/23922059
- close_wait问题分析流程
https://mp.weixin.qq.com/s?__biz=MzI4MjA4ODU0Ng==&mid=402163560&idx=1&sn=5269044286ce1d142cca1b5fed3efab1&3rd=MzA3MDU4NTYzMw==&scene=21#wechat_redirect
- tcpdump和wireshark使用
https://www.cnblogs.com/pyng/p/9698723.html