【问题标题】:Java memory settings in a docker containerDocker 容器中的 Java 内存设置
【发布时间】:2021-03-14 19:05:30
【问题描述】:

我有一个基于 Java8 OpenJDK 的 Java 应用程序。它运行在一个限制为 20GB 的 docker 容器中。

tomcat的-Xms和-Xmx设置如下:

-Xms = 60% 的容器内存(由 cgroup 指定) - 所以 12GB -Xmx = 80% 的容器内存(由 cgroup 指定) - 所以 16GB

这会在容器上留下 4GB 的空闲空间,这通常很好,但有时在负载下我看到 docker 容器退出(并且 java 进程被杀死)并出现 OOM,因为容器内存使用量已超过 20GB。

我知道 -Xmx 设置用于堆,而不是整个 Java 进程和 JVM,因此希望容器上的 4GB 'headroom' 就足够了,但似乎不是。

我知道所有用例都大相径庭,但我的问题是,一般而言,对于内存限制为 20GB 的容器而言,设置 -Xmx 设置是否太高。

我在玩弄使用 MaxRAM 设置的想法,我知道这只是决定堆内存,但我不确定这是否会产生积极影响?

您通常是使用 MaxRAM 或 -Xmx,还是同时设置两者有什么好处?

如果我使用 MaxRAM 而不是 -Xmx,java 将如何为堆分配内存?是否有一个简单的算法来解决这个问题,例如 MaxRAM 设置的 50%? java 这样做会更有效地管理内存吗?

【问题讨论】:

  • MaxHeapSize 计算为 ContainerSize * MaxRAMPercentage。默认情况下,MaxRAMPercentage 为 25(最大容器大小的 25%)。我总是设置 -XX:MaxRAMPercentage=70.0(75 或 80 太多了,一段时间后我得到了 OOM)并且从不设置 -Xmx。有了这个设置我没有任何OOM
  • @OctavianR。并非所有 JDK 8 版本都使用该逻辑
  • @OneCricketeer 感谢您的更正(我没有检查所有 JVM 的发行版),我的上述评论适用于 AdoptOpenJDK 和可能的其他发行版。如果您想检查此计算是否适用于其他 JVM,则可以列出 JVM 的标志 java -XX:+PrintFlagsFinal (for Molenpad)
  • @Octa 百分比标志在 8u192 左右被反向移植。任何早期的 JDK8 版本都没有用于任何发行版,AFAIK
  • @OneCricketeer 我明白了,(我想我记得 AdoptOpenJDK 1.8 也是这样的),那么在使用 -XX:MaxRAMPercentage 之前使用 -XX:+PrintFlagsFinal 应该可以解决这个问题。如果它不存在,那么要么使用更新版本的 JVM,要么他应该设置 -Xmx

标签: java docker memory jvm


【解决方案1】:

一般来说,对于内存限制为 20GB 的容器,设置 -Xmx 设置是否过高

这取决于。应用程序可以使用比指定的-Xmx 更少的 RAM,以及比指定的-Xmx 多 2 倍或 3 倍的 RAM。这两种应用我见过很多。

what takes memory in a Java process

与其尝试根据给定的容器限制(这些限制可能完全不相关)猜测适当的堆大小,不如将-Xmx 设置为适合您的特定应用程序的值?我的意思是,如果您的应用程序仅使用 8 GB 堆就可以正常工作,那么即使容器允许,也无需提供更多。

您通常是使用 MaxRAM 或 -Xmx,还是同时设置两者有什么好处?

两者都设置没有意义,因为Xmx 会覆盖MaxRAM

我要使用 MaxRAM 而不是 -Xmx,java 将如何为堆分配内存?是否有一个简单的算法来解决这个问题,例如 MaxRAM 设置的 50%?

What is the difference between xmx and MaxRAM JVM parameters?

java 这样做会更有效地管理内存吗?

没有。 MaxRAM 仅影响堆大小和默认垃圾收集器的计算(未明确指定时)。

【讨论】:

    猜你喜欢
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多