JAVA / HEAP - 奇怪的垃圾收集行为导致服务器性能下降

问题描述 投票:0回答:1

申请背景:

我们在 Tomcat 服务器上有一个供多个用户使用的 Java Web 应用程序。我们有 30 多个客户服务器正在运行。

问题:

在一个特定的客户身上,我们遇到了一个关于内存使用的奇怪现象。系统运行了几个小时/几天,相当不错,但一段时间后,服务器性能由于 CPU 负载而下降,我认为这是因为 MemoryUsage / GC。

见解:

从屏幕截图中可以看出,我们有大约 14GB 可用内存,应用程序保留了大约 5GB 的堆,并且还使用了 5GB。正如您所看到的,堆空间和已用堆逐渐接近,直到 GP 升级并且服务器性能下降越来越多。

事件

1.)当客户打电话给我时,我进行了堆转储
2.) 一半用户注销后(转储)
3.)所有用户注销后(转储)

用于比较:这是正常行为,正如预期的那样(注销后同一服务器,无需重新启动):

事件发生后

问题:

为什么 GC 尝试清理越来越多的数据,却没有增加堆大小? 如何进一步调试呢? 任何朝正确方向的推动都会有所帮助,并且非常感激。

我尝试解释 JFR 文件、HEAP 转储。但它并没有引导我走向任何特定的方向。问题不在于分配的对象,而在于 GC 的升级,并且 APP 不仅仅会占用更多的堆大小。

java performance garbage-collection heap-memory visualvm
1个回答
0
投票

为什么 GC 尝试清理越来越多的数据,却没有增加堆大小?

  1. GC 处于反复耗尽空间的模式。 每次发生这种情况时,都会触发 GC。 当您越来越接近抛出 OOME 的点时,GC 会变得越来越频繁。 (有一些方法可以避免这种 GC“死亡螺旋”行为......但这是另一个问题。)

  2. 您的堆已经达到 5GB ...您在 JVM 选项中设置的最大堆大小。 它无法增加堆大小。

如何进一步调试?

有两种可能性。

  • 如果您(在您的应用程序中)存在内存泄漏,那么您需要找到并修复它。 有很多查找和修复 Java 内存泄漏的资源。

  • 如果您没有内存泄漏,那么您要么需要增加最大堆大小,要么需要优化或调整应用程序以减少其堆使用量。


问题不在于分配的对象,而在于 GC 的升级,并且 APP 不仅仅会占用更多的堆大小。

除了增加 JVM 的

-Xmx
设置之外,没有简单的解决方案。

但是,您可以调整 GC 开销限制设置(请参阅调整 GC 开销超出参数)。 如果限制较低,则会导致 GC 抛出

OutOfMemoryError
earlier。 您可以安排 OOME 触发应用程序 JVM 的重新启动。 这可能比应用程序运行缓慢更容易被接受。

© www.soinside.com 2019 - 2024. All rights reserved.