【问题标题】:Automatically configure Java to use the maximum RAM allocated to its Docker container自动配置 Java 以使用分配给其 Docker 容器的最大 RAM
【发布时间】:2016-04-08 06:25:40
【问题描述】:

如果我使用docker run --memory=X 通过 Bash 脚本运行 Java 应用程序,有没有办法让这个 Bash 脚本可靠地推断已为容器分配了多少内存?基本上,我希望这个 Bash 脚本执行以下操作:

#!/bin/bash

# (Do some other stuff...)

MAX_RAM="$(get-max-ram)"
exec java "-Xms${MAX_RAM}" "-Xmx${MAX_RAM}" -jar my_jar.jar

另外,如果我执行上述操作,我是否应该让 Java 使用比最大 RAM 少一点?

【问题讨论】:

  • 不要忘记 PermSize ;) (然后不要使用最大 RAM ..)
  • @Gaël permsize 从 Java 8 开始就无关紧要了。
  • 确实,取决于您的 Java 版本。感谢您的精确度。
  • 好点,谢谢!顺便说一句,我正在使用 Java 7。

标签: java bash docker


【解决方案1】:

Docker 使用cgroups 来实现资源限制。在容器内部,您可以使用cgget 实用程序来打印各种子系统(在本例中为memory 子系统)的参数。

例如,考虑一个内存限制为 64G 的容器(毕竟是 Java):

> docker run --memory=64G

在容器内,然后使用cgget读取memory.limit_in_bytes参数的当前值:

> cgget -nvr memory.limit_in_bytes /
68719476736

请注意,您可能必须首先通过容器映像的包管理器安装 cgget 二进制文件。在 Ubuntu 上,您需要 cgroup-bin 包。

然后您可以使用此值来动态计算您的 JVM 参数(仅作为示例,根据您自己的需要进行调整):

MAX_RAM=$(cgget -nvr memory.limit_in_bytes /)
JVM_MIN_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.2" | bc))
JVM_MAX_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.8" | bc))
exec java "-Xms${JVM_MIN_HEAP}" "-Xmx${JVM_MAX_HEAP}" -jar my_jar.jar

重要提示:在没有内存限制的情况下运行(即没有--memory=X 标志),memory.limit_in_bytes 参数仍然有一个值,尽管大小在 2^63 - 4096 左右:

> cgget -nvr memory.limit_in_bytes /
9223372036854771712

除非您想以大约 8 EB 的最小堆空间启动 JVM,否则您的入口点脚本也应该考虑这种情况:

MAX_RAM=$(cgget -nvr memory.limit_in_bytes /)
if [ $MAX_RAM -le 137438953472 ] ; then
    JVM_MIN_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.2" | bc))
    JVM_MAX_HEAP=$(printf "%.0f" $(echo "${MAX_RAM} * 0.8" | bc))
else
    JVM_MIN_HEAP=32G
    JVM_MAX_HEAP=128G
fi

exec java "-Xms${JVM_MIN_HEAP}" "-Xmx${JVM_MAX_HEAP}" -jar my_jar.jar

【讨论】:

  • 在您的示例中没有明确指出。但是您是否将 max 和 min 相乘以小于容器,以便 JVM 可以在容器可能退出之前处理 OOM 情况?
  • 作为后备,我将使用此答案中的 limit_in_bytes/proc/meminfo 中的 MemTotal(以 kB 为单位)的最小值
【解决方案2】:
  • java5/6/7/8u131-:简单但有效的方法,可以使用java -Xmx cat /sys/fs/cgroup/memory/memory.limit_in_bytes(windows除外)

  • java8u131+ 和 java9+: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 可以完成这项工作。

  • java 8u191+:UseContainerSupport 默认开启。此功能是从 java10 向后移植的,但目前尚未向后移植到 java9。

  • java10+:UseContainerSupport默认开启。

参考:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-21
    • 2018-02-21
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2020-11-11
    相关资源
    最近更新 更多