早期时候,容器内运行Java应用程序时,Jvm无法感知容器环境存在,所以对容器资源的限制比如内存或者cpu等都无法生效。原因是容器的资源管理使用了操作系统cgroup机制,但是Jvm无法感知cgroup。所以可能需要在Jvm以及Pod、Docker中指定两次内存限制。
-XX:+UseContainerSupport
:JVM 已被修改为知道它正在 Docker 容器中运行,并将提取容器特定的配置信息,而不是查询操作系统。提取的信息是已分配给容器的 CPU 数量和总内存。Java 进程可用的 CPU 总数是根据任何指定的 cpu 集、cpu 份额或 cpu 配额计算得出的。此支持仅在基于 Linux 的平台上可用。这个新的支持默认启用 。禁用:-XX:-UseContainerSupport
。-XX:ActiveProcessorCount=${cpu_num}
:此计数会覆盖 JVM 中的任何其他自动 CPU 检测逻辑。-XX:InitialRAMPercentage
、-XX:MaxRAMPercentage
、-XX:MinRAMPercentage
:允许 Docker 容器用户对将用于 Java 堆的系统内存量进行更细粒度的控制。以上是截止文章发布时对容器环境资源的相关更新,以下内容是基于Java SE 8u371进行开启容器环境感知测试:
$java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal
#部分输出
bool UseCGroupMemoryLimitForHeap = false {experimental} {default}
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap/
OracleJDK 64-Bit Server VM warning: Unable to open cgroup memory limit file /sys/fs/cgroup/memory/memory.limit_in_bytes (No such file or directory)
$stat -fc %T /sys/fs/cgroup
cgroup2fs
-XX:MaxRAM=`cat /sys/fs/cgroup/memory.max`
-XX:ActiveProcessorCount=2 -Xmx4g
到这为止,Java SE 8开启容器特性支持失败,这方面有坑,建议直接上Java SE 11,用起来很香,不用额外配置,当然默认最大堆内存比例还是25%,需要改成100%,推荐改成75%。
下面是社区讨论: