提问者:小点点

为什么Java只为110 Gb的k8s pod分配了36 Gb的内存


我在Kubernetes中有大约112 GB内存的容器。其中部署了一个java应用程序(Spring Boot)。打印参数显示了这一点

...Application - -server -Dspring.profiles.active=prod -Xms110g -Xmx110g

JVM的输出显示只有36GB的堆可用于进程。

private static final long GIGABYTE = 1024L * 1024L * 1024L;

public static float bytesToGigabytes(long bytes) {
    return Math.floorDiv(bytes / GIGABYTE, 3);
}

public void getMemUsed() {
    // Get the Java runtime
    Runtime runtime = Runtime.getRuntime();
    // Run the garbage collector
    runtime.gc();
    // Calculate the used memory
    long memory = runtime.totalMemory() - runtime.freeMemory();
    log.info("RAM Used %.3fGb of %.3fGb (max %.3fGb)".formatted(
            bytesToGigabytes(memory), bytesToGigabytes(runtime.totalMemory()), bytesToGigabytes(runtime.maxMemory())));

}

印刷品

RAM Used 0.000Gb of 36.000Gb
...
RAM Used 29.000Gb of 36.000Gb

而像“heap”和“jps”这样的工具则展示了另一幅画面

    free -h
              total        used        free      shared  buff/cache   available
Mem:          125Gi       102Gi        15Gi       118Mi       8.3Gi        22Gi
Swap:            0B          0B          0B

top shell命令输出

PS:当内存增长到33-35 GB以上时,pod会重新启动

可能与此Linux有关:由于虚拟内存限制,无法在单个进程中分配超过32 GB/64 GB的内存


共1个答案

匿名用户

解决。只需添加此 JVM 参数

-XX:+UseContainerSupport -XX:MaxRAMPercentage=100

并将内存计算功能更改为

log.info("RAM used {} of {} (max {})", FileUtils.byteCountToDisplaySize(memory),
            FileUtils.byteCountToDisplaySize(runtime.totalMemory()),
            FileUtils.byteCountToDisplaySize(runtime.maxMemory()));