> 文章列表 > 容器环境Java的改进

容器环境Java的改进

容器环境Java的改进

Docker 和 K8S 的兴起,很多服务已经运行在容器环境。对于 Java 程序,JVM 设置是一个重要的环节.

非容器环境

非容器环境下,如果不指定最大堆内存,默认每个 JVM 最多使用 25% 的机器内存

如果指定JVM的最大堆内存,可以通过-Xmx指定最大堆内存

java -XX:+PrintFlagsFinal -Xmx1024m -version | grep -Ei "maxheapsize|maxram"uintx DefaultMaxRAMFraction                     = 4                                   {product}uintx MaxHeapSize                              := 1073741824                          {product}uint64_t MaxRAM                                    = 137438953472                        {pd product}uintx MaxRAMFraction                            = 4                                   {product}double MaxRAMPercentage                          = 25.000000                           {product}
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

但是需要注意的是,JVM 实际使用的内存会比 heap 内存大:

JVM内存  = heap 内存 + 线程stack内存 (XSS) * 线程数 + 启动开销(constant overhead)

默认的 XSS 通常在 256KB 到 1MB,也就是说每个线程会分配最少 256K 额外的内存, constant overhead 是 JVM 分配的其他内存。

容器环境的 Java Heap

但在容器环境下,Java 获取不到容器的内存限制(request、limit),只能获取到node节点的配置,因此无法使用JVM的默认配置。
如果使用-Xmx的配置方式,例如配置了容器限制使用1G内存,还需要再配置JVM的启动参数,徒增运维的复杂度。

为了解决这个问题,Java 10 引入了 +UseContainerSupport(默认情况下启用),通过这个特性,可以使得 JVM 在容器环境分配合理的堆内存。并且,在 JDK8U191 版本之后,这个功能引入到了 JDK 8。

UseContainerSupport

https://www.oracle.com/java/technologies/javase/8u191-relnotes.html

JDK 10 中引入了以下更改,以改进在 Docker 容器中运行的 Java 的执行和可配置性:

  • JDK-8146115改进 docker 容器检测和资源配置使用

JVM 已被修改为知道它在 Docker 容器中运行,并将提取容器特定的配置信息而不是查询操作系统。提取的信息是已分配给容器的 CPU 数量和总内存。Java 进程可用的 CPU 总数是根据任何指定的 cpu 集、cpu 份额或 cpu 配额计算的。此支持仅适用于基于 Linux 的平台。默认情况下启用此新支持,可以在命令行中使用 JVM 选项将其禁用:

-XX:-UseContainerSupport

此外,此更改添加了一个 JVM 选项,该选项提供了指定 JVM 将使用的 CPU 数量的能力:

-XX:ActiveProcessorCount=count

此计数会覆盖 JVM 中的任何其他自动 CPU 检测逻辑。

  • JDK-8186248允许更灵活地选择可用 RAM 的堆百分比

添加了三个新的 JVM 选项,以允许 Docker 容器用户对将用于 Java 堆的系统内存量进行更细粒度的控制:

  • -XX:InitialRAMPercentage
  • -XX:MaxRAMPercentage
  • -XX:MinRAMPercentage

这些选项取代了已弃用的分数形式(-XX:InitialRAMFraction-XX:MaxRAMFraction-XX:MinRAMFraction)。

  • JDK-8179498 attach in linux 应该相对于 /proc/pid/root 和命名空间感知

此错误修复更正了尝试从主机进程附加到在 Docker 容器中运行的 Java 进程时的附加机制。

请参阅JDK-8146115

最佳实践

设置 -XX:+UseContainerSupport,设置 -XX:MaxRAMPercentage=75.0,这样为其他进程(debug、监控)留下足够的内存空间,又不会太浪费 RAM。

注意:如果设置了-Xms,-XX:InitialRAMPercentage选项将被忽略。如果设置了-Xmx,-XX:MaxRAMPercentage选项将被忽略