我正在 AWS ECS(Docker 容器)上运行 dropwizard REST 应用程序。 应用程序大小从 512MiB、1/4/8 GiB 不等。 我正在使用G1GC。
在高负载下, JVM 使用的堆增加(具有锯齿模式)。 因此,JVM 的提交内存也会增加。
当应用程序的负载减少回到空闲状态时(在我的测试中,根本没有负载),JVM 提交的内存不会被释放。 使用的堆具有锯齿状模式,但峰值要大得多(我的猜测是,由于存在已提交的内存,因此在年轻垃圾收集触发之前,JVM 使用了更多的堆内存)。
ECS 任务(~kubernetes pod)内存使用情况考虑 JVM 提交的内存来计算已用内存。
我希望 JVM 在负载峰值后释放已提交的内存,以便 ECS 任务内存利用率降低,从而我们可以根据 ECS-Task 内存使用指标缩小系统规模。
我尝试使用 -XX:MaxHeapFreeRatio 来确保释放内存,但这仅在完整的 GC 周期期间有效,不会被触发(除非我手动触发它)。 我认为 G1GC 试图阻止 Full GC。
我的问题是,如何触发完整GC,或者如何确保已提交的内存被释放回来,以便我的系统可以根据内存使用指标进行缩减。
更新: 我的解决方案可能是在系统没有流量时通过 System.gc() 触发 Full GC。 我希望找到一个 JVM 参数,可以在保留过多堆时触发 GC 或减少声明的堆。
奇怪的是 JVM 不返还内存,这是自动缩放的一大缺点。
您正在运行 JDK 11。
JDK 12 中已实现使用 G1 GC 取消未使用堆的提交。