java -XX:MaxRAMFraction=1 在容器环境中用于生产是否安全?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49854237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is -XX:MaxRAMFraction=1 safe for production in a containered environment?
提问by atamanroman
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.
Java 8/9 带来了对-XX:+UseCGroupMemoryLimitForHeap
(with -XX:+UnlockExperimentalVMOptions
) 的支持。这将设置-XX:MaxRAM
为 cgroup 内存限制。默认情况下,JVM 分配大约 25% 的最大 RAM,因为-XX:MaxRAMFraction
默认值为 4。
Example:
例子:
MaxRAM = 1g
MaxRAMFraction = 4
JVM is allowed to allocate: MaxRAM / MaxRAMFraction = 1g / 4 = 256m
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.
对于(通常)由单个 JVM 进程组成的部署,仅使用 25% 的配额似乎是浪费。所以现在人设-XX:MaxRAMFraction=1
,所以理论上允许JVM使用100%的MaxRAM。
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.
对于 1g 示例,这通常会导致堆大小约为 900m。这似乎有点高 - JVM 或其他东西(如远程 shell 或进程外任务)没有太多可用空间。
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:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
) 是否被认为对生产甚至最佳实践是安全的?或者我仍然应该手动选择-Xmx
, -Xms
,-Xss
等等?
采纳答案by atamanroman
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).
我们做了一些简单的测试,结果表明设置-XX:MaxRAM=$QUOTA
并-XX:MaxRAMFraction=1
导致在负载下杀死容器。JVM 分配了超过 900M 的堆,这太多了。-XX:MaxRAMFraction=2
似乎安全(ish)。
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.
请记住,您可能希望为其他进程留出空间,例如docker exec
在容器中获取调试外壳 ( ) 或诊断。
Edit: we've written up what we've learned in detail in an article. Money quotes:
编辑:我们已经在一篇文章中详细记录了我们所学到的知识。金钱报价:
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.
TL'DR:Java 内存管理和配置仍然很复杂。尽管自 Java 9/8u131 以来 JVM 可以读取 cgroup 内存限制并相应地调整内存使用情况,但这不是金子弹。您需要知道做什么
-XX:+UseCGroupMemoryLimitForHeap
,并且需要为每个部署微调一些参数。否则,您可能会浪费资源和金钱,或者在最糟糕的时间杀死您的容器。-XX:MaxRAMFraction=1
特别危险。Java 10+ 带来了很多改进,但仍然需要手动配置。为了安全起见,对你的东西进行负载测试。
and
和
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.
最优雅的解决方案是升级到 Java 10+。Java 10 弃用了
-XX:+UseCGroupMemoryLimitForHeap
(11) 并引入了-XX:+UseContainerSupport
(12),后者取代了它。它还引入了-XX:MaxRAMPercentage
(13),它采用 0 到 100 之间的值。这允许对允许 JVM 分配的 RAM 量进行细粒度控制。由于+UseContainerSupport
默认情况下启用,所以一切都应该开箱即用。
Edit #2: we've written a little bit moreabout -XX:+UseContainerSupport
编辑 #2:我们已经写了更多关于-XX:+UseContainerSupport
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.
Java 10 引入
+UseContainerSupport
(默认启用)使 JVM 在容器环境中使用合理的默认值。自 8u191 以来,此功能向后移植到 Java 8,这可能允许大量 Java 部署在野外正确配置其内存。
回答by a.l.
The recent oracle-jdk-8(8u191) brings the following options to allow Docker container users to gain more fine grained control over the amount of system memory that will be used for the Java Heap:
最近的 oracle-jdk-8(8u191) 提供了以下选项,以允许 Docker 容器用户对将用于 Java 堆的系统内存量进行更细粒度的控制:
-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage
Three new JVM options have been added to allow Docker container users to gain more fine grained control over the amount of system memory that will be used for the Java Heap:
-XX:InitialRAMPercentage -XX:MaxRAMPercentage -XX:MinRAMPercentage These options replace the deprecated Fraction forms (-XX:InitialRAMFraction, -XX:MaxRAMFraction, and -XX:MinRAMFraction).
添加了三个新的 JVM 选项以允许 Docker 容器用户对将用于 Java 堆的系统内存量进行更细粒度的控制:
-XX:InitialRAMPercentage -XX:MaxRAMPercentage -XX:MinRAMPercentage 这些选项替换了已弃用的分数形式(-XX:InitialRAMFraction、-XX:MaxRAMFraction 和 -XX:MinRAMFraction)。
See https://www.oracle.com/technetwork/java/javase/8u191-relnotes-5032181.html
见https://www.oracle.com/technetwork/java/javase/8u191-relnotes-5032181.html