有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

AWS JVM CPU限制上的java Docker

我在AWS Fargate服务上的docker容器中启动了spring引导应用程序,因此一旦CPU消耗达到100%以上,容器就会因docker错误而停止

Reason: OutOfMemoryError: Container killed due to memory usage

在指标上,我们可以看到CPU超过100%。貌似经过一段时间的评测之后,我们发现了CPU消耗代码,但我的问题是,CPU怎么能超过100%呢

这是说JVM只使用100%的方式吗

我记得我们在内存消耗方面也有类似的问题。我读了很多关于cgroup的文章,发现解决方案可以指定

-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,但它告诉我

As of Java SE 8u131, and in JDK 9, the JVM is Docker-aware with respect to Docker CPU limits transparently. That means if -XX:ParalllelGCThreads, or -XX:CICompilerCount are not specified as command line options, the JVM will apply the Docker CPU limit as the number of CPUs the JVM sees on the system. The JVM will then adjust the number of GC threads and JIT compiler threads just like it would as if it were running on a bare metal system with number of CPUs set as the Docker CPU limit.

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

共 (1) 个答案

  1. # 1 楼答案

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

    Number of CPUs


    Use a combination of number_of_cpus() and cpu_sets() in order to determine how many processors are available to the process and adjust the JVMs os::active_processor_count appropriately. The number_of_cpus() will be calculated based on the cpu_quota() and cpu_period() using this formula: number_of_cpus() = cpu_quota() / cpu_period(). If cpu_shares has been setup for the container, the number_of_cpus() will be calculated based on cpu_shares()/1024. 1024 is the default and standard unit for calculating relative cpu usage in cloud based container management software.

    Also add a new VM flag (-XX:ActiveProcessorCount=xx) that allows the number of CPUs to be overridden. This flag will be honored even if UseContainerSupport is not enabled.

    因此,在AWS上,您通常在任务定义级别设置cpu共享。 在jvm修复之前,它的计算不正确

    关于java8版本<;191:cpu_shares()/1024=256/1024=被标识为2

    在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"
    

    我希望它能帮助一些人,因为我在任何地方都找不到答案(SpringIssuesTracker、AWS支持等)