Tomcat 增加并消耗所有可用的 CPU

Tomcat spiking and consuming all available CPU

Tomcat (8.0.14-1+deb8u1) in production server suddenly hogs all CPU, 可以做些什么来诊断原因?我知道分析器可能会派上用场,但在生产环境中没有用,有什么想法吗?

附加信息: "top" command execution / lsb_release

@Gonzalo 我看到你已经提供了几乎所有必要的信息,但我将从 "beginning" 中写下我的答案,这样它可以对偶然发现它的经验不足的用户有所帮助。

  1. 您应该进行线程转储。您可以通过以下任一方式做到这一点:

    • kill -3 PID
    • jstack -F PID
  2. 查看 tophtop 命令输出。

    • 对于top按"shift + h"显示线程(您也可以从顶部开始top -p PID以过滤掉不相关的进程)
    • 找出哪个线程消耗了CPU并记下线程ID
    • 线程ID为十进制,需要转为十六进制。
  3. 打开线程转储并查找它的十六进制线程。这是消耗 CPU

  4. 的线程

PS:您的线程转储看起来很奇怪,并且缺少线程 ID。线程堆栈应该像这样开始:

"Finalizer" daemon prio=8 tid=0x02b3d000 nid=0x898 in Object.wait() [0x02d0f000]
...stack traces here...

其中 nid 是您从 top/htop 中找到的十六进制线程 ID。

尝试使用 kill -3

进行转储

我们的几台服务器都遇到了同样的问题。问题也出现在 tomcat 没有网络应用程序的服务器上,只提供静态页面。 cpu 使用率突然飙升至 200% 并且再也没有下降

这个问题在我们最近升级到 8.0.14 和 8_u_121

之前从未出现过

设置如下:

  • debian 8.1,最新补丁
  • tomcat 8.0.14
  • oracle jvm 8_u_121(截至该日期最新)
  • 2,4 和 8 GB 内存(取决于服务器)
  • http/1.1 80 上的连接器重定向到 443; 443 上带有 https 的 nio1 连接器(实际上在 8080 和 8443 上,防火墙映射 80 到 8080 和 443 到 8443)

出现问题时症状如下:

  • cpu 进程使用率 200% "java",没有下降
  • 内存消耗正常
  • apps.log
  • 中没有日志条目
  • 在catalina.out中约有20个条目如下:

30-Jan-2017 10:15:38.479 INFO [http-nio-8080-exec-16] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. 30-Jan-2017 10:15:40.022 INFO [http-nio-8080-exec-17] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level. 30-Jan-2017 10:15:41.574 INFO [http-nio-8080-exec-18] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header

当我们升级到 8.0.14 时,我们在 catalina.out 中收到了类似的错误消息。这是因为此版本不再接受 url 中未转义的 { 和 }。我们通过更改客户端代码将这些字符编码为 %4B 和 %4D 来修复它。当时没有 cpu 问题