Java应用程序的垃圾收集器在POD Kubernetes中不能释放内存。

3
我在应用程序的垃圾收集器方面遇到了问题,我正在使用GCP环境与Kubernetes和BigTable作为数据源。当接收到负载时,应用程序不释放内存空间并且填满直到k8s重新启动POD。我使用分析器来查看JVM的行为,这是结果。在“Old Gen”池中可以看到内存已满,但它从未释放空间并且填满直到重新启动和再次启动。

Old Gen

在“伊甸空间”池中,当它正在填充时,空间被释放并且永远不会达到极限。

Eden Space

这是在创建Docker镜像以在K8s中部署时的JVM配置。

java
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC
-XX:+UseCGroupMemoryLimitForHeap
-XX:+AlwaysPreTouch
-XX:ParallelGCThreads=5
-XX:GCTimeRatio=4
-XX:MaxGCPauseMillis=100
-XX:MinHeapFreeRatio=30
-XX:MaxHeapFreeRatio=30
-Xms512m
-Xmx4608m

在另一个进行REST调用且从未出现内存填充问题的应用程序中,应用了相同的配置。

Java版本为1.8

感谢您的帮助。

问候。


1
请尝试通过使用-XX:+PrintGCDetails和-XX:+PrintGCTimeStamps来启用额外的日志记录,以查看垃圾回收行为。根据您的图表,我可以得出结论:"在“Old Gen”池中,我们可以看到内存已满,但它从未释放空间,直到重新启动并再次开始填充。" - undefined
1个回答

2
首先,您需要确定问题的根本原因才能进一步进行。我建议您使用-XX:+PrintGCDetails和-XX:+PrintGCTimeStamps收集有关该主题的更多信息。如果您的假设“Old Gen”池从未释放空间是正确的(老实说,从图像上并不明显),则可以尝试以下几个技巧来处理它:
  • 通过-XX:MaxNewSize,-XX:NewSize,-XX:MaxOldSize,-XX:MaxOldSize直接指定新旧gc大小,以确保老年代有足够的空间
  • 通过-XX:+PrintGCDetails和-XX:+PrintGCTimeStamps收集更多日志,查看是否由于某个代的过度利用而导致任何问题
  • 尝试通过-XX:SurvivorRatio增加幸存者空间比率,以加快老年代对象的收集

感谢您的回答,正如您所提到的,问题出在一些对象ExecutorService在多个线程中没有正确关闭,现在它已经正常工作了。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接