关于java:JAVA问题排查系列Java-Web-请求僵死无法响应线程被占满

94次阅读

共计 797 个字符,预计需要花费 2 分钟才能阅读完成。

记一次 Java Web 服务申请僵死的状况,起因是因为申请线程池死锁占满,无奈接管新的申请。以下为这次问题的排查过程:

1、网站告警某个实例无奈响应,找到对应的实例,手动 curl 申请接口,无奈响应。

2、应用 jps 命令找到对应过程的过程号。

3、应用 jstat 查看 GC 是否还失常执行,残缺命令:jstat -gcutil 1624 1s,每隔 1s 打印一次内存及 gc 状况,如下图:

从上图看出基本上内存没有啥变动,也不现执行 GC,一方面阐明过程基本上没有执行啥工作;另一方面也能够反映 JVM 并没有齐全僵死,还在存活(内存有大量的变动)。再看一张前面执行的 gc 状况,如下图:

基本上也能看出进行了一次 GC,列 YGC 次数比上一张图片减少了一次。

4、再应用 jmap -heap 1647 确认 JVM 内存并没有压力,如下图:

5、查看一下线程的状况 jstack -l 1647 > jstack-20201224.log , 并将后果输入到文件中,不便排查。关上文件发现有大量以 qtp 为结尾命名的线程,统计一下,如下图:

经查,因为我的项目应用的是 jetty 容器,申请线程池中的线程命名就是这样的命名,很显著,线程被占满了,并且不开释。再看一下失常的 JVM 实例是什么样的?

线程数才 28 个。再确认下异样线程的状态:

6、关上方才导出的查看线程的文件,找下具体什么起因导致线程无奈开释,如下图:

能够看到是因为线程阻塞在 BasicFuture.get() 办法处,进而看到本人的代码调用地位位于 ProcessTaskQueryResultService.java 的 198 行,如下图:

能够看到代码应用了 Apache 的 httpasyncclient 库的异步调用,返回 Future,如果申请异样,在此处就是申请了一个比拟大的响应后果,接口比拟消耗资源,导致无奈响应,将始终阻塞在 Future.get() 处,最好的方法就是设置获取后果的超时工夫,如上图改后的示例。

正文完
 0