使用jstack解决线程爆满问题
创始人
2024-05-16 11:51:36
0
    • 问题发现

生产应用现存在问题,影响到系统的使用,前端页面只配置了35个派生指标,后台任务生成20000多线程任务,占用了全部资源,导致其他系统也没资源可用,指标工厂也无法进一步使用,今天上午发的死锁也应该是这个原因引起的,在配置初期没有存在死锁的问题,派生指标配置的越来越多,后面配置的派生指标出现死锁的问题也越来越多,现在有5台机器,都已经快到机器的极限值,从前台配置和后台生成任务的比例来看,现在的代码应该是存在bug,或者在任务架构方面需要修改。

其中一台机器线程查询如下:

查看用户进程

[bdpcloud@host167 da]$ ps -u bdpcloud -L | wc -l

5348

统计RUNNABLE线程数量

[bdpcloud@host167 da]$ jstack 319012 > thread.txt

[bdpcloud@host167 da]$ grep RUNNABLE thread.txt | wc -l

92

    • 现场日志提取

使用jstack命令提取线程日志,命令是:jstack PID

[nmportal@hhhtsjzx-app04-1-2 bin]$ /opt/nmportal/jdk1.8/bin/jstack 2625 > a.txt

2023-01-18 16:26:13

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):

"Attach Listener" #4493 daemon prio=9 os_prio=0 tid=0x00007fb3b81b9000 nid=0x5623 waiting on condition [0x0000000000000000]

java.lang.Thread.State: RUNNABLE

"I/O dispatcher 4016" #4481 prio=5 os_prio=0 tid=0x00007fb32c51a000 nid=0x1896 runnable [0x00007fb0e0e65000]

java.lang.Thread.State: RUNNABLE

at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)

at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)

at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)

at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)

- locked <0x00000000a3901d98> (a sun.nio.ch.Util$3)

- locked <0x00000000a3901d88> (a java.util.Collections$UnmodifiableSet)

- locked <0x00000000a3901da8> (a sun.nio.ch.EPollSelectorImpl)

at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)

at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:255)

at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)

at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)

at java.lang.Thread.run(Thread.java:748)

经过统计,类似于这个线程为RUNNABLE状态的,多达8588个,基本上确定是应用代码存在问题

    • 问题排查过程

既然定位到是代码创建线程的问题,那就候找到这个代码是哪里创建的,看了一下这个报错日志,报错的类不是jdk自带的就是框架自带的,日志信息量小,感觉无从下手。我们先找到日志里面的报错信息,看报错涉及的类AbstractMultiworkerIOReactor和线程名称I/O dispatcher,还好这个写了线程的名称,我们根据类名和线程的名称找到到了代码创建的位置

但是这个也并没有什么用,无法根据这些信息查找到是创建的源头是我们的哪里的代码问题,再看一下AbstractMultiworkerIOReactor这个类,去百度搜索一下,查看一下相关信息,从某种关系来说,和httpasynclient有着某种关系,找不到关系,也只能边找百度,边尝试猜测是哪里引用了,也许是运气比较好,查找第一个类就定位到问题所在了。

我们查看代码,搜一下哪里使用了httpsyn类似的方法或者类

最终找到一个可疑的地方,在创建AsyncRestTemplate的时候,用了 @Scope("prototype"),即原型,就是多例的意思,而问题在于这个AsyncRestTemplate里面,每次都会创建一个AsyncRestTemplate都会创建一个新的HttpComponentsAsyncClientHttpRequestFactory,而这个线程池并不会关闭,所以调用了这个同步的方法,就会创建越来越多的线程。把这个 @Scope("prototype")去掉即可

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...