处于等待状态的Apache Tomcat线程具有100%的CPU利用率

时间:2010-09-23 17:08:00

标签: apache tomcat tomcat6

应用程序在受到负载时,有时会使用100%。

做一个kill -quit <pid>在等待状态下显示了1100多个线程:

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

"http-8080-1198" daemon prio=10 tid=0x00007f17b465c800 nid=0x2061 in Object.wait() [0x00007f1762b6e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00007f17cb087890> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458)
        - locked <0x00007f17cb087890> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484)
        at java.lang.Thread.run(Thread.java:619)

"http-8080-1197" daemon prio=10 tid=0x00007f17b465a800 nid=0x2060 in Object.wait() [0x00007f1762c6f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00007f17cb14f460> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458)
        - locked <0x00007f17cb14f460> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484)
        at java.lang.Thread.run(Thread.java:619)
............

即使取消部署应用程序上下文或重新启动数据库,状态也不会更改。

请提出可能的原因。

App Server:Apache Tomcat 6.0.26

最大主题:1500

处于等待状态的主题:1138

2 个答案:

答案 0 :(得分:4)

“在上等待”不是问题。线程正在等待通知 - 在这种情况下,它被锁定在JIoEndpoint.Worker

  

侦听的后台线程   传入的TCP / IP连接和手   将它们送到合适的处理器上。

所以我认为这是在等待实际的请求。

首先,当你有许多线程due to high amount of context switching时,CPU利用率实际上会增加。你真的需要1500吗?你能尝试减少吗?

其次,它是否经常占用内存或GC-ing?

如果您看到这些内容,那么“等待 ”就会出现问题。你有没有BLOCKED(在对象监视器上)或等待堆栈跟踪中的lock()?

答案 1 :(得分:0)

在Solaris系统上,您可以使用命令

prstat -L -p <pid> 0 1 > filename.txt

这将为您分解在CPU上工作的每个进程,并将基于轻量级处理器ID而不是PID。当您查看线程转储时,您可以将轻量级进程与您的NID(或TID,具体取决于实现)进行匹配,它们显示在线程转储的顶行。通过匹配这两个东西,您将能够分辨出哪些线程是CPU占用的。

以下是输出的示例。

   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU   PROCESS/LWPID
   687 user      1024M  891M sleep   59    0   0:40:07 12.0% java/5
   687 user      1024M  891M sleep   59    0   0:34:43 15.3% java/4
   687 user      1024M  891M sleep   59    0   0:17:00 7.6%  java/3
   687 user      1024M  891M sleep   59    0   1:00:07 31.4% java/2

然后使用相应的线程转储,您可以找到这些线程

"GC task thread#0 (ParallelGC)" prio=3 tid=0x00065295 nid=0x2 runnable
"GC task thread#1 (ParallelGC)" prio=3 tid=0x00012345 nid=0x3 runnable
"GC task thread#2 (ParallelGC)" prio=3 tid=0x0009a765 nid=0x4 runnable
"GC task thread#3 (ParallelGC)" prio=3 tid=0x0003456b nid=0x5 runnable

因此,在高CPU情况下,问题出现在垃圾收集中。通过将nid与LWPID字段匹配可以看出这一点

如果这会帮助你,我会建议制作一个脚本,将输出你的prstat和CPU使用率一次性。这将为您提供最准确的应用程序表示。

按照原来的两个帖子,@ joseK是正确的。这些线程正在等待接收用户的请求。那里没有问题。