ECS容器中JVM内存增长超出限制

4

我的任务定义已配置这些限制:

"cpu": "1024",
"memory": "8192"

我正在使用 "docker" 控制组标志在 Docker 容器内运行 jar 文件:

java -XX:+UseContainerSupport -XX:MaxRAMPercentage=80 -XX:InitialRAMPercentage=70 /myjar.jar foo.Main

但 ECS 通过 OOM 错误导致我的服务出现问题。

我已经测量了 JVM 的内存使用情况,并通过以下调试措施在应用程序中报告:

val bean: MemoryMXBean = ManagementFactory.getMemoryMXBean
val hmu: MemoryUsage = bean.getHeapMemoryUsage
val nhu = bean.getNonHeapMemoryUsage
... reporting these metrics ...

在这张图片中,顶部显示的是 CloudWatch 报告的已使用内存情况。正如您所看到的,它已经达到了100%。
底部的图表显示的是应用程序报告的内存使用情况。
val pc = (1.0 * hmu.getUsed) / hmu.getCommitted

根据文档:

 * Below is a picture showing an example of a memory pool:
 *
 * <pre>
 *        +----------------------------------------------+
 *        +////////////////           |                  +
 *        +////////////////           |                  +
 *        +----------------------------------------------+
 *
 *        |--------|
 *           init
 *        |---------------|
 *               used
 *        |---------------------------|
 *                  committed
 *        |----------------------------------------------|
 *                            max
    /**
     * Returns the amount of memory in bytes that is committed for
     * the Java virtual machine to use.  This amount of memory is
     * guaranteed for the Java virtual machine to use.
     *
     * @return the amount of committed memory in bytes.
     *
     */
    public long getCommitted() {
        return committed;
    };

/**
     * Returns the amount of used memory in bytes.
     *
     * @return the amount of used memory in bytes.
     *
     */
    public long getUsed() {
        return used;
    };

我的Docker文件非常简单:
FROM openjdk:10-jdk

COPY service.jar /affinity-service.jar
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]

start.sh是:

#!/bin/bash
set -x

OPTS=""

#... setting flags from ENV values...
#...
#...

java -XX:+UseContainerSupport -XX:MaxRAMPercentage=80 -XX:InitialRAMPercentage=70 ${OPTS} -jar /service.jar com.....Service

请进一步阐述,我不明白你的问题是什么。 - Michael
为什么 ECS 的内存使用率会增长到 100%,而 JVM 报告的要少得多。JVM 内存图表在几个小时内非常一致和稳定。此外,使用 -XX:+UseContainerSupport -XX:MaxRAMPercentage=80 -XX:InitialRAMPercentage=70 分配的内存似乎超过了容器限制允许的内存。 - Avba
我怀疑 MaxRAMPercentage 无法读取容器限制并获取主机 RAM。参见 https://ops.tips/blog/why-top-inside-container-wrong-memory/。 - Tilo
帮助文档声称可以阅读它:https://www.eclipse.org/openj9/docs/xxusecontainersupport/ - Tilo
1个回答

6
MaxRAMPercentageInitialRAMPercentage标志不会限制Java进程的内存。
这些标志唯一影响的是堆大小 - 有关详细信息,请参见此答案

正如我在这里所解释的那样,Java进程可以使用比堆大小更多的内存

不幸的是-仅使用JVM标志设置硬内存限制以保证JVM永远不会被操作系统杀死是不可能的。但是,同一答案可能会给出分析Java进程内存占用的想法。


在Docker容器中运行应用程序服务器时,需要添加哪些推荐标志以遵守高级别限制? - Avba
@AvnerBarr 推荐使用那些未设置的标志,即具有默认值的标志。所有其他标志都应用于解决特定问题。如果您想查看Java进程为什么消耗太多内存,我建议从本地内存跟踪开始。 - apangin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接