3

今天发现我的服务器cpu负载太高,服务器只是运行一个Java应用。

下面是我的操作步骤。

  1. 我使用top命令来查找应用程序的 pid。PID 为 25713。

  2. 我使用top -H -p 25713命令找到了一些使用最多 cpu 的 pid。比如25719 tomcat 20 0 10.6g 1.5g 13m R 97.8 4.7 314:35.22 java

  3. 我使用jstack -F 25713命令打印转储信息。例如"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable

  4. 我从转储文件中搜索了 pid。然后我发现使用cpu最多的pids都像"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable

  5. 我使用jstack命令后,cpu就正常了!

以下是我的问题:

  1. 为什么GC Threadscpu负载太高。
  2. 为什么我使用jstack命令后cpu变得正常。

不止这一次,每一次。

这是一些正常的日志。2015-10-10T10:17:52.019+0800: 71128.973: [GC (Allocation Failure) 2015-10-10T10:17:52.019+0800: 71128.973: [ParNew: 309991K->206K(348416K), 0.0051145 secs] 616178K->306393K(1009920K), 0.0052406 secs] [Times: user=0.09 sys=0.00, real=0.01 secs]

当 CPU 过高时,GC 日志停留在 中[GC (Allocation Failure) 2015-10-10T10:18:10.564+0800: 71147.518: [ParNew:,没有其他日志。

当我执行jstack命令时,打印日志

2015-10-10T10:17:50.757+0800: 53501.137: [GC (Allocation Failure) 2015-10-10T10:17:50.757+0800: 53501.137: [ParNew: 210022K->245K(235968K), 369.6907808 secs] 400188K->1
90410K(1022400K), 369.6909604 secs] [Times: user=3475.15 sys=11.69, real=369.63 secs] 
4

2 回答 2

4

只是猜测,您可能会受到某些内核版本中存在的futex_wait 错误的影响。

更一般地,jstack -F向进程发送一个信号,这将中断任何可能正在休眠的线程。所以也许 GC 线程只是在等待另一个以某种方式错过唤醒的线程。即,如果它确实卡在 GC 中并发送信号修复了问题,那么这可能指向锁定或内存排序错误,如果不在内核中,那么在 JVM 中。

jstack -F您可以尝试发送到进程,而不是使用SIGBREAK,看看是否具有相同的效果。

于 2015-10-10T08:05:58.190 回答
0

为什么 GC 线程使 cpu 负载过高。

您的 JVM 可能正在运行完整的 GC。而且由于您的 JVM 可能正在运行一个巨大的堆(由 10.6 GB 的内存大小暗示),这将需要很长时间。您的系统也可能正在颠簸虚拟内存。

为什么在我使用 jstack 命令后 cpu 变得正常。

巧合……大概吧。GC 在您运行 jstack 时完成。


如果您想对此进行调查,我建议您打开垃圾收集日志记录,并尝试将高 CPU 负载的时间段与 GC 活动相关联。

GC 日志应该告诉您的另一件事是您的 Tomcat 堆是否太满。如果您的 webapps 有内存泄漏,那么这将导致堆填满无法被垃圾回收的对象。随着时间的推移,这将导致 JVM 花费越来越多的时间来运行 GC。如果这是问题所在,那么您需要查找并修复内存泄漏。

于 2015-10-10T02:20:30.377 回答