Docker在AWS JVM CPU上的限制

时间:2019-06-04 15:23:30

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

我在AWS Fargate服务上的docker容器中启动了我们的spring boot应用程序,因此一旦CPU消耗超过100%,该容器就会因错误而停止Docker OOM-killer

  

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

根据度量标准,我们可以看到CPU变得超过100%。经过一段时间的分析,似乎我们发现了占用CPU的代码,但我的问题是,CPU的性能如何能超过100%?

是否可以说JVM仅使用100%?

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

  

-XX:+ UnlockExperimentalVMOptions -XX:+ UseCGroupMemoryLimitForHeap

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

进行调整
  

-XX:MaxRAMFraction = 2

这将为堆分配docker内存的1/2。 我应该为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

1 个答案:

答案 0 :(得分:0)

我找到了问题的答案。 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修复之前,它的计算不正确。

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

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