-XX:MaxRAMFraction=1 对容器环境中的生产安全吗?

2022-01-16 00:00:00 docker jvm java

Java 8/9 带来了对 -XX:+UseCGroupMemoryLimitForHeap 的支持(使用 -XX:+UnlockExperimentalVMOptions).这会将 -XX:MaxRAM 设置为 cgroup 内存限制.默认情况下,JVM 分配大约 25% 的最大 RAM,因为 -XX:MaxRAMFraction 默认为 4.

Java 8/9 brought support for -XX:+UseCGroupMemoryLimitForHeap (with -XX:+UnlockExperimentalVMOptions). This sets -XX:MaxRAM to the cgroup memory limit. Per default, the JVM allocates roughly 25% of the max RAM, because -XX:MaxRAMFraction defaults to 4.

例子:

MaxRAM = 1g
MaxRAMFraction = 4
JVM is allowed to allocate: MaxRAM / MaxRAMFraction = 1g / 4 = 256m

对于(通常)由单个 JVM 进程组成的部署而言,仅使用 25% 的配额似乎是一种浪费.所以现在人们设置-XX:MaxRAMFraction=1,所以理论上允许JVM使用100%的MaxRAM.

Using only 25% of the quota seems like waste for a deployment which (usually) consists of a single JVM process. So now people set -XX:MaxRAMFraction=1, so the JVM is theoretically allowed to use 100% of the MaxRAM.

对于 1g 示例,这通常会导致堆大小约为 900m.这似乎有点高 - JVM 或其他东西(如远程 shell 或进程外任务)没有太多可用空间.

For the 1g example, this often results in heap sizes around 900m. This seems a bit high - there is not a lot of free room for the JVM or other stuff like remote shells or out-of-process tasks.

那么这种配置(-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1)对于产品甚至最佳实践来说是安全的吗?还是我还是应该手动选择-Xmx-Xms-Xss等等?

So is this configuration (-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1) considered safe for prod or even best practice? Or should I still hand pick -Xmx, -Xms, -Xss and so on?

推荐答案

我们做了一些简单的测试,结果表明设置 -XX:MaxRAM=$QUOTA-XX:MaxRAMFraction=1 导致负载下的容器被杀死.JVM 分配了超过 900M 的堆,这太多了.-XX:MaxRAMFraction=2 看起来很安全(ish).

We did some simple testing which showed that setting -XX:MaxRAM=$QUOTA and -XX:MaxRAMFraction=1 results in killed containers under load. The JVM allocates more than 900M heap, which is way too much. -XX:MaxRAMFraction=2 seems safe(ish).

请记住,您可能希望为其他进程留出空间,例如在容器中获取调试外壳 (docker exec) 或诊断.

Keep in mind that you may want to leave headroom for other processes like getting a debug shell (docker exec) or diagnostics in the container.

我们已经在 文章.金钱报价:

we've written up what we've learned in detail in an article. Money quotes:

TL'DR:Java 内存管理和配置仍然很复杂.尽管自 Java 9/8u131 起 JVM 可以读取 cgroup 内存限制并相应地调整内存使用,但这并不是万能的.您需要知道 -XX:+UseCGroupMemoryLimitForHeap 做了什么,并且需要为每次部署微调一些参数.否则,您可能会浪费资源和金钱,或者在最糟糕的时候杀死您的容器.-XX:MaxRAMFraction=1 特别危险.Java 10+ 带来了很多改进,但仍然需要手动配置.为了安全起见,请对您的东西进行负载测试.

TL'DR: Java memory management and configuration is still complex. Although the JVM can read cgroup memory limits and adapt memory usage accordingly since Java 9/8u131, it’s not a golden bullet. You need to know what -XX:+UseCGroupMemoryLimitForHeap does and you need to fine tune some parameters for every deployment. Otherwise you risk wasting resources and money or getting your containers killed at the worst time possible. -XX:MaxRAMFraction=1 is especially dangerous. Java 10+ brings a lot of improvements but still needs manual configuration. To be safe, load test your stuff.

最优雅的解决方案是升级到 Java 10+.Java 10 弃用了 -XX:+UseCGroupMemoryLimitForHeap (11) 并引入了取代它的 -XX:+UseContainerSupport (12).它还引入了 -XX:MaxRAMPercentage (13),取值介于 0 和 100 之间.这允许对 JVM 允许分配的 RAM 量进行细粒度控制.由于 +UseContainerSupport 默认启用,所以一切都应该开箱即用.

The most elegant solution is to upgrade to Java 10+. Java 10 deprecates -XX:+UseCGroupMemoryLimitForHeap (11) and introduces -XX:+UseContainerSupport (12), which supersedes it. It also introduces -XX:MaxRAMPercentage (13) which takes a value between 0 and 100. This allows fine grained control of the amount of RAM the JVM is allowed to allocate. Since +UseContainerSupport is enabled by default, everything should work out of the box.


编辑 #2:我们已经写了一点 关于-XX:+UseContainerSupport

Java 10 引入了 +UseContainerSupport(默认启用),这使得 JVM 在容器环境中使用正常的默认值.自 8u191 以来,此功能已向后移植到 Java 8,这可能允许大量 Java 部署在野外正确配置其内存.

Java 10 introduced +UseContainerSupport (enabled by default) which makes the JVM use sane defaults in a container environment. This feature is backported to Java 8 since 8u191, potentially allowing a huge percentage of Java deployments in the wild to properly configure their memory.

相关文章