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

记一次 Java Web 服务请求僵死的情况,原因是因为请求线程池死锁占满,无法接收新的请求。以下为这次问题的排查过程:

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

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

3、使用 jstat 查看GC是否还正常执行,完整命令:jstat -gcutil 1624 1s,每隔 1s 打印一次内存及 gc 情况,如下图:
JAVA问题排查系列:Java Web 请求僵死,无法响应,线程被占满_第1张图片
基本上也能看出进行了一次 GC,列 YGC 次数比上一张图片增加了一次。

4、再使用 jmap -heap 1647 确认 JVM 内存并没有压力,如下图:
JAVA问题排查系列:Java Web 请求僵死,无法响应,线程被占满_第2张图片

5、查看一下线程的情况 jstack -l 1647 > jstack-20201224.log ,并将结果输出到文件中,方便排查。打开文件发现有大量以 qtp 为开头命名的线程,统计一下,如下图:
image.png

6、打开刚才导出的查看线程的文件,找下具体什么原因导致线程无法释放,如下图:
JAVA问题排查系列:Java Web 请求僵死,无法响应,线程被占满_第3张图片
可以看到代码使用了 Apache 的 httpasyncclient 库的异步调用,返回 Future,如果请求异常,在此处就是请求了一个比较大的响应结果,接口比较耗费资源,导致无法响应,将一直阻塞在 Future.get() 处,最好的办法就是设置获取结果的超时时间,如上图改后的示例。

你可能感兴趣的:(java)