【问题标题】:Docker on AWS JVM CPU limitAWS JVM CPU 限制上的 Docker
【发布时间】:2019-10-20 03:52:32
【问题描述】:

我在 AWS Fargate 服务的 docker 容器中启动我们的 Spring Boot 应用程序,因此一旦 CPU 消耗达到 100% 以上,容器就会停止 Docker OOM-killer 并出现错误

原因:OutOfMemoryError:容器因内存使用而被杀死

在指标上,我们可以看到 CPU 变得超过 100%。经过一段时间的分析,我们似乎发现了消耗 CPU 的代码,但我的问题是,CPU 怎么能超过 100%?

是不是说 JVM 只使用了 100%?

我记得我们在内存消耗方面遇到过类似的问题。看了很多关于cgroups的文章,发现解决方法是指定

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

因此,当您使用选项 -m=512 启动 docker 时,堆大小将是 mac 大小的 1/4。堆大小也可以通过选项调整

-XX:MaxRAMFraction=2

这将为堆分配 1/2 的 docker 内存。 我应该对 CPU 使用类似的东西吗? 我读了文章https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits,但它告诉我们

从 Java SE 8u131 开始,在 JDK 9 中,JVM 支持 Docker 透明地尊重 Docker CPU 限制。这意味着如果 -XX:ParalllelGCThreads 或 -XX:CICompilerCount 未指定为命令行选项,JVM 将应用 Docker CPU 限制作为 JVM 在系统上看到的 CPU 数量。然后JVM会调整 GC 线程和 JIT 编译器线程的数量就像它一样 就好像它在设置了 CPU 数量的裸机系统上运行一样 作为 Docker CPU 限制。

Docker命令用来启动

docker run -d .... -e JAVA_OPTS='-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+PrintFlagsFinal -XshowSettings:vm' -m=512 -c=256 ...

使用Java版本

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

启动过程中有关应用程序的一些附加信息

VM settings:
    Max. Heap Size (Estimated): 123.75M
    Ergonomics Machine Class: client
    Using VM: OpenJDK 64-Bit Server VM

ParallelGCThreads                         = 0   
CICompilerCount                          := 2
CICompilerCountPerCPU                     = true

【问题讨论】:

    标签: java amazon-web-services docker aws-fargate


    【解决方案1】:

    我找到了我的问题的答案。 识别要使用的处理器数量的行为已在 https://bugs.openjdk.java.net/browse/JDK-8146115

    中修复

    CPU 数量


    使用 number_of_cpus() 和 cpu_sets() 的组合来确定有多少处理器可用 进程并调整 JVM os::active_processor_count 适当地。 number_of_cpus() 将根据 cpu_quota() 和 cpu_period() 使用这个公式: number_of_cpus() = cpu_quota() / cpu_period()。如果 cpu_shares 已为 容器,number_of_cpus() 将根据 cpu_shares()/1024。 1024 是默认和标准单位 计算基于云的容器管理中的相对 CPU 使用率 软件。

    还添加一个新的 VM 标志 (-XX:ActiveProcessorCount=xx),它允许 要覆盖的 CPU 数量。这面旗帜将被尊重,即使 未启用 UseContainerSupport。

    因此,在 AWS 上,您通常会在任务定义级别设置 cpu_shares。 在 jvm fix 之前计算不正确。

    在 java8 版本

    在java8版本> 191上迁移后:cpu_shares()/1024 = 256/1024 = 被识别为1

    要测试的代码

    val version = System.getProperty("java.version")
    val runtime = Runtime.getRuntime()
    val processors = runtime.availableProcessors()
    logger.info("========================== JVM Info ==========================")
    logger.info("Java version is: {}", version)
    logger.info("Available processors: {}", processors)
    

    样本输出

    "Java version is: 1.8.0_212"
    "Available processors: 1"
    

    我希望它对某人有所帮助,因为我在任何地方都找不到答案(spring-issues-tracker、AWS 支持等)

    【讨论】:

      猜你喜欢
      • 2011-10-03
      • 2021-03-29
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 2016-09-26
      • 2019-06-14
      相关资源
      最近更新 更多