调试 JBoss 100% CPU 使用率

调试 JBoss 100% CPU 使用率

我们使用 JBoss 运行两个 WAR。一个是我们的 Web 应用程序,另一个是我们的 Web 服务。Web 应用程序访问另一台计算机上的数据库并向 Web 服务发出请求。Web 服务向其他计算机发出 JMS 请求,汇总数据并返回数据。

在我们最大的客户那里,JBoss Java 进程大约每月会占用 100% 的 CPU。运行 JBoss 的机器有 8 个 CPU。在此期间,我们的 Web 应用程序仍可访问,但页面加载需要大约 3 分钟。重新启动 JBoss 即可恢复正常。

数据库机器和所有其他机器都正常,只有运行 JBoss 的机器受到影响。内存使用率正常。网络利用率正常。JBoss 日志中没有可疑错误消息。

我已设置了一个尽可能接近客户生产环境的测试环境,并使用多达 2 倍的并发用户数进行了负载测试。但我的测试环境并未重现该问题。

我们接下来该怎么做?我们如何才能缩小问题范围?

目前我们唯一的计划是等到问题在生产中自行发生,然后进行一些调试以确定原因。到目前为止,人们在问题发生时只是重新启动 JBoss,以尽量减少停机时间。下次发生这种情况时,他们会找开发人员来看看。问题是,下次发生这种情况时,可以做些什么来确定原因?

我们可以在同一台机器上设置一个单独的 JBoss 实例,并将 Web 应用程序与 Web 服务分开安装。这样,当问题再次发生时,我们就会知道哪个 WAR 有问题(假设是我们的代码)。但这并不能缩小范围。

我应该启用 JMX 远程吗?这样下次出现问题时,我就可以连接 VisualVM,查看哪些线程占用了 CPU 以及它们到底在做什么。但是,在生产环境中启用 JMX 远程是否会带来重大的负面影响?

还有其他方法可以查看哪些线程正在占用 CPU 并获取堆栈跟踪来查看它们在做什么吗?

还有其他想法吗?

谢谢!

答案1

您可以向正在运行的 JVM 发送 SIGQUIT 信号,以便将每个线程的堆栈跟踪打印到标准输出。这不会终止进程,但我认为在打印堆栈跟踪时它确实会让所有线程进入休眠状态。

然后,将列出的线程 ID 与查看线程 CPU 利用率的首选方法关联起来。 prstat -L对于 Solaris,top -H对于 Linux。请注意,java 堆栈跟踪中的 tid 以十六进制打印;与 top 或 prstat 输出进行比较时,您可能需要将其转换为十进制。

答案2

我执行了线程转储。但是,在我的生产系统上,除非使用某些参数启动 JVM,否则无法执行此操作,而这些参数在生产系统中永远不会启用。在这种情况下,我使用 JMX 控制台的 jboss.system:type=ServerInfo mbean 执行线程转储 (listThreadDump())。

当我没有编写代码时,线程转储输出对我来说大多毫无意义。但编写代码的人可能能够理解它。在这些线程转储无济于事的情况下,我更喜欢使用“ strace -fp <PID of JBoss' java process> -o outfile.txt”来从另一个角度了解系统调用级别上发生的事情。这有点像从消防水管中喝水,但有时它很有帮助。

相关内容