Tomcat 的 Catalina 实用程序线程定期使用高 CPU 和内存

Posted

技术标签:

【中文标题】Tomcat 的 Catalina 实用程序线程定期使用高 CPU 和内存【英文标题】:Tomcat's Catalina utility threads are periodically using high CPU and memory 【发布时间】:2021-10-19 02:05:22 【问题描述】:

我们有一个 web 应用,它在空闲时平均使用 20% 的 CPU,没有网络流量或任何类型的请求。 它在 Java 11、Tomcat 9、Spring Framework 5.3、Hibernate 5.4 上运行。 然而,我将在下面描述的问题在 Java 8、Tomcat 8.5、Spring 4.3 和 Hibernate 4 上也是如此。 我尝试使用 JFR 和 JMC 来分析应用程序,并尝试了很多配置。 在上图中,看起来 catalina-utility-1 和 catalina-utility-2 线程会定期唤醒,并在几秒钟内使用大量 CPU。 这些线程似乎还分配了大量内存,在采样的 5 分钟间隔内总共分配了 30+ GB。

对于此分析,我已将 JFR 配置为最多记录所有内容,启用所有选项。

当我试图通过查看 Method Profiling 详细信息来深入挖掘细节时,我发现它似乎与 org.apache.catalina.webresources.Cache.getResource() 有关。

所以我开始阅读有关 Tomcat 缓存的信息,并尝试了不同的参数来通过 context.xml 文件调整它,如下所示:

<Context>
  <!-- Default set of monitored resources. If one of these changes, the    -->
  <!-- web application will be reloaded.                                   -->
  <WatchedResource>WEB-INF/web.xml</WatchedResource>
  <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
  <WatchedResource>$catalina.base/conf/web.xml</WatchedResource>
  <!-- Uncomment this to disable session persistence across Tomcat restarts -->
  <!--
    <Manager pathname="" />
    -->
  <Resources cachingAllowed="true" cacheMaxSize="3024000" cacheObjectMaxSize="10240" cacheTtl="10000"/>
</Context>

在这个用于 JFR 分析的特定示例中,我将缓存大小增加到 3GB,将cacheTtl 增加到 10 秒。我认为更大的缓存和更大的 TTL 会影响 CPU 峰值的间隔,因为我怀疑 Tomcat 每 5 秒检查一次缓存(最初大小为 1G),这是默认设置。 但是,无论我为缓存大小或 ttl 设置什么值,周期性的 CPU 峰值都是相同的。 缓存大小足以容纳 Tomcat 想要放入的任何内容,因为在我们在日志中看到警告后我增加了该值。无论如何,1GB 足以消除警告。

我还尝试了从 1 到 5GB 的堆大小,上面的分析是使用 5GB 的堆大小完成的。如果不开始达到物理内存限制,我真的不能超过这个值。

从 Java 8 天开始,我们就使用 G1GC 作为我们的垃圾收集器。调整其参数不会影响 CPU 使用率。 我也尝试了 ParallelGC 和 SerialGC,但 CPU 使用模式保持不变。

在 Google 上搜索此类问题会导致没有结果,我完全被困在我还能尝试什么或应该看什么的问题上。

欢迎提出任何建议。谢谢。


更新 1:

似乎我最初遇到了格式问题,并且在解析时 context.xml 中缺少开头的 &lt;context&gt; 标记。修好了。

我也尝试过,按照&lt;Context reloadable="false"&gt; 的建议,将 reloadable 明确设置为 false。完全没有效果。

是否可以从其他任何地方设置可重新加载标志?我推测即使在context.xml 中它被设置为false,也可能会应用其他文件或设置。

【问题讨论】:

【参考方案1】:

图像中的堆栈跟踪包含对 Loader#modified 的调用,并且仅当您将上下文的 reloadable 属性设置为 true 时才可能:

<Context reloadable="true">
...
</Context>

如Tomcat's documentation中所述:

如果您希望 Catalina 监视 /WEB-INF/classes//WEB-INF/lib 中的类的更改,请设置为 true,并在检测到更改时自动重新加载 Web 应用程序。此功能在应用程序开发过程中非常有用,但它需要显着的运行时开销,因此不建议在已部署的生产应用程序中使用。这就是为什么这个属性的默认设置是 false

(强调我的)。

reloadable 设置为false(或删除属性)以消除开销。

【讨论】:

感谢您的建议。它没有用。我更新了答案并修复了隐藏初始 &lt;context&gt; 标记的格式问题。 您是否检查了所有可能的位置?这可以在conf/Catalina/localhost/&lt;appname&gt;.xmlwebapps/&lt;appname&gt;/META-INF/context.xmlconf/Catalina/localhost/context.xml.defaultconf/context.xml(与$CATALINA_BASE 相关的所有文件夹)中设置。 你是个天才Piotr!似乎 7 年前有人参与该项目,尽管在 webapps/root/META-INF 文件夹中有一个 context.xml 并在其上设置 reloadable="true" 是个好主意。我在这个项目上工作了大约 6 年,我从未接触或知道我们项目的 git 存储库中的 context.xml 文件。惊人的!现在 CPU 使用率基本为零。

以上是关于Tomcat 的 Catalina 实用程序线程定期使用高 CPU 和内存的主要内容,如果未能解决你的问题,请参考以下文章

最实用解决tomcat startup.bat 一闪而过

TomcatTomcat的类加载机制

Linux系统实用命令总结

IntelliJ 说'无法运行程序'/path/to/tomcat/bin/catalina.sh' 错误=13 权限被拒绝

$catalina_home/lib 中带有 mysql 驱动程序的 maven tomcat 插件

Tomcat Guice/JDBC 内存泄漏