我有一个 Java 应用程序在 Kubernetes 集群的容器 (eclipse-temurin:21-jre-alpine) 中运行,我正在尝试优化其内存使用情况。
所需的堆大小非常尖。默认情况下,除非收到非常大的请求,否则几乎不需要内存。然而,有时,大堆是必要的。
我正在努力让 JVM 在正常情况下使用尽可能少的 RAM,但仍然允许内存使用量偶尔出现峰值,而不会导致容器崩溃。
我为容器设置了 1GB 的 Kubernetes 资源限制,JVM 选取了该资源限制。配置此限制后,RAM 使用量从 4GB 下降到 400MB,服务质量没有明显下降。
但是,有时,应用程序需要针对某些请求加载高达 3GB 的内存,从而导致容器由于 1GB 硬限制而崩溃。
如何配置 JVM 和 Kubernetes 以设置硬限制(例如 5GB),但确保 JVM 在正常情况下使用最少的 RAM?
受到this SO answer的启发,我设置了以下 JVM 参数,大部分解决了问题:
-XX:+UseG1GC -XX:MaxHeapFreeRatio=5 -XX:MinHeapFreeRatio=2
现在我可以设置较高的内存限制,例如 5GB,以防峰值需要大量内存,但通常的 RAM 使用量仍将低于 1GB。
显然 JVM 确实喜欢保留内存,即使某些东西被垃圾收集,它也不会释放到操作系统,以防将来可能需要它。