【问题标题】:JVM memory is growing beyond limit in ECS containerJVM 内存增长超出 ECS 容器的限制
【发布时间】:2019-04-02 05:02:34
【问题描述】:

我的任务定义配置有以下限制:

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

我正在使用“docker”cgroup 标志在 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 ...

在图片中,顶部是 cloud-watch 报告的已用内存。如您所见,它是 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

【问题讨论】:

  • 请详细说明,我不明白你的问题是什么。
  • 为什么 ECS 内存使用量增长到 100%,而 JVM 报告的却少得多。 JVM 内存图在几个小时内非常一致且稳定。此外,使用-XX:+UseContainerSupport -XX:MaxRAMPercentage=80 -XX:InitialRAMPercentage=70 分配的内存似乎超出了容器限制所允许的内存
  • 我怀疑 MaxRAMPercentage 无法读取容器限制并获取主机 RAM。 ops.tips/blog/why-top-inside-container-wrong-memory
  • 帮助声称他们可以阅读:eclipse.org/openj9/docs/xxusecontainersupport

标签: java docker jvm amazon-ecs


【解决方案1】:

MaxRAMPercentageInitialRAMPercentage 标志限制 Java 进程的内存。
这些标志唯一影响的是堆大小 - 有关详细信息,请参阅this answer

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

坏消息是 - 仅使用 JVM 标志来设置硬内存限制是不可能的,以保证 JVM 永远不会被操作系统杀死。但是same answer 可能会告诉您如何分析 Java 进程的内存占用。

【讨论】:

  • 在遵守高级限制的 docker contianer 中运行应用程序服务器时,推荐添加哪些标志?
  • @AvnerBarr 推荐的标志是那些未设置的标志,即具有默认值。所有其他都应该用于解决特定问题。如果你想了解为什么 Java 进程会消耗太多内存,我建议从 Native Memory Tracking 开始。
猜你喜欢
  • 2014-02-09
  • 1970-01-01
  • 2016-09-26
  • 2020-10-15
  • 2017-09-12
  • 2018-11-01
  • 2018-03-30
  • 1970-01-01
  • 2016-11-25
相关资源
最近更新 更多