【发布时间】:2016-05-13 20:22:49
【问题描述】:
我有一个在 Tomcat7 实例上运行的 Java 应用程序。我正在使用 Java 8。
现在在我的应用程序中有一个格式为:http://zzz.xxx.zzz.xxx/someWebservice?somepar1=rrr&somePar2=yyy 的网络服务。这将返回一个最多 10 个字符的 String 值。
我现在已经开始使用 Jmeter 对该服务进行负载测试。我正在加载 100 个并发连接并获得大约150 requests/second 的吞吐量。服务器是一台 4 核 6GB 机器,只运行 Tomcat(应用程序实例)。数据库实例在单独的机器上运行。 JVM 以最小 2GB 和最大 4 GB 内存分配运行。最大永久大小为 512 MB。 Tomcat 有足够的线程来满足我的负载(最大连接数/线程数/执行程序值已正确设置)
我现在正在尝试优化此服务,为此我正在尝试分析内存消耗。我也在使用JConsole。我的 CPU 使用率不是问题,但是当我查看内存 (HEAP) 使用情况时,我觉得有些不对劲。我观察到的是一个锯齿形图,我知道这是正确的,因为常规 GC 会清除堆内存。
我担心这个锯齿形图形有上升趋势。我的意思是锯齿中的波谷似乎随着时间的推移而增加。随着这种趋势,最终我的服务器在一小时左右达到最大堆内存,然后稳定在 4GB。我相信如果我加载一个 CONSTANT 负载,那么堆内存利用率应该有一个恒定的趋势,即一个锯齿图,其峰值和谷值对齐。如果有上升趋势,我怀疑随着时间的推移收集的变量存在内存泄漏,并且由于 GC 无法清除它们,因此一段时间内会增加。我附上截图。
问题:
1)。这是正常行为吗?如果是,那么为什么尽管负载没有变化,但堆却不断增加?我不认为 100 个线程的负载应该在大约 30 分钟内使 4GB 堆饱和。
2)。这里的潜在原因是什么?我需要查看内存泄漏吗?除了 JConsole 之外的任何 JVM 分析器都可以帮助我查明 GC 无法清除的变量吗?
【问题讨论】:
-
如果真的有内存泄漏,如果你让它运行足够长的时间,最终你会得到一个内存不足的错误。是这样吗?您可以通过减小最大堆大小来更轻松地进行测试。
-
@Gimby:谢谢。我运行了一天,没有看到任何“OOM 错误”。但我也读到内存泄漏并不总是表现为 OOM 错误。我的问题仍然是为什么上升趋势?上升趋势是“正常行为”吗?麻烦的是,如果你看到你的堆在很小的负载下就满了,那么你就很难调整你的应用程序的大小。
-
如果它被清理干净,它不是泄漏。我不是堆分析专家,但我可以说我自己在大型应用程序中看到了这种“上升”趋势。如果您想深入了解这一点,那么您的任务就是潜入 Java 内存管理的美妙世界——相当困难的文档。仅仅盯着数字和图表不会告诉你原因。
标签: java tomcat memory-leaks jvm heap-memory