我们有一个JAVA应用程序通过消耗一些(未知的)资源来阻止其他组件创建新线程,从而使我们的redhat服务器(30核/ 512Go ram)崩溃了,我们目前正在通过杀死正在散布线程的进程来解决此问题每次问题出现时(大约每15天一次),我们尝试在/etc/security/limits.conf中设置巨大的值,但是在达到该限制之前我们已经找到问题的解决方法。
我上次使用ps -efL |计算了线程数| wc -l,知道当时的CPU / RAM消耗很低,对于我们的野兽来说,有10000个线程很多吗?我用gstack尝试找出它卡在哪里,但是由于它是一个JAVA程序idk,如果输出有意义?但是我可以在那里找到一个模式:9000个线程中的大多数看起来像这样:
Thread 9049 (Thread 0x7f43d5087700 (LWP 123925)):
#0 0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2 0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3 0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4 0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5 0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6 0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7 0x00007f43d722f1ad in clone () from /lib64/libc.so.6
Thread 9048 (Thread 0x7f43d4f86700 (LWP 123926)):
#0 0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2 0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3 0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4 0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5 0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6 0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7 0x00007f43d722f1ad in clone () from /lib64/libc.so.6
同样在杀死进程之前,我使用了gcore -o /tmp/dump.txt,这是获取Java进程的核心文件的正确方法吗?
我上次使用ps -efL |计算了线程数| wc -l,知道当时的CPU / RAM消耗很低,对于我们的野兽来说,有10000个线程很多吗?
这是不是一个微不足道的数目的线程,但没有,10K线程是不是说多了,特别是对于一个30核心机。我目前使用的4核心Windows桌面大约有3K。
我用gstack尝试找出它卡在哪里,但是由于它是一个JAVA程序idk,如果输出有意义?
我从未尝试使用本机线程堆栈调试Java,但是对我来说,该堆栈跟踪看起来像一个“驻留”线程。换句话说,某个线程池中的某个线程与工作无关,因此正在等待工作。有关更多详细信息,请参见此答案。
同样在杀死进程之前,我使用了gcore -o /tmp/dump.txt,这是获取Java进程的核心文件的正确方法吗?
它可能具有一定的价值,但我建议为该工作使用特定于Java的工具。首先想到的是jcmdJDK附带的。这是一个入门的链接。Java 9的版本有一些更好的文档,并且非常相似。
我专门要做的是使用Thread.print命令jcmd打印Java级别的堆栈跟踪并将GC.heap_dump整个Java堆转储到.hprof文件中,然后可以通过MAT之类的工具进行分析。
如果您将JDK 8与“ Commercial Features”一起使用,则还可以启用JFR(Java Flight Recorder,该程序可以跟踪流程的执行。可以使用Oracle的“ Mission Control”或“另一种“任务控制”,例如来自Azul的任务,称为Zulu。
最后,您还可以尝试使用jconsole连接到该过程,jconsole是JDK附带的另一个工具。
祝好运。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。