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
中缺少开头的 <context>
标记。修好了。
我也尝试过,按照<Context reloadable="false">
的建议,将 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
(或删除属性)以消除开销。
【讨论】:
感谢您的建议。它没有用。我更新了答案并修复了隐藏初始<context>
标记的格式问题。
您是否检查了所有可能的位置?这可以在conf/Catalina/localhost/<appname>.xml
、webapps/<appname>/META-INF/context.xml
、conf/Catalina/localhost/context.xml.default
和conf/context.xml
(与$CATALINA_BASE
相关的所有文件夹)中设置。
你是个天才Piotr!似乎 7 年前有人参与该项目,尽管在 webapps/root/META-INF
文件夹中有一个 context.xml 并在其上设置 reloadable="true"
是个好主意。我在这个项目上工作了大约 6 年,我从未接触或知道我们项目的 git 存储库中的 context.xml
文件。惊人的!现在 CPU 使用率基本为零。以上是关于Tomcat 的 Catalina 实用程序线程定期使用高 CPU 和内存的主要内容,如果未能解决你的问题,请参考以下文章
IntelliJ 说'无法运行程序'/path/to/tomcat/bin/catalina.sh' 错误=13 权限被拒绝