Java AWS JVM CPU限制上的Docker

Java AWS JVM CPU限制上的Docker,java,amazon-web-services,docker,aws-fargate,Java,Amazon Web Services,Docker,Aws Fargate,我在AWS Fargate服务上的docker容器中启动了spring引导应用程序,因此一旦CPU消耗达到100%以上,容器就会因docker错误而停止 原因:OutOfMemoryError:由于内存使用而导致容器死亡 在指标上,我们可以看到CPU超过100%。貌似经过一段时间的评测之后,我们发现了CPU消耗代码,但我的问题是,CPU怎么能超过100%呢 这是说JVM只使用100%的方式吗 我记得我们在内存消耗方面也有类似的问题。我读了很多关于cgroup的文章,发现解决方案可以指定 -XX:

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

原因:OutOfMemoryError:由于内存使用而导致容器死亡

在指标上,我们可以看到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使用类似的东西吗? 我读过这篇文章,但它说明了这一点

从JavaSE8U131开始,在JDK9中,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

我找到了我问题的答案。 确定要使用的处理器数量的行为在中是固定的

CPU数量


使用_cpu()的数量_和cpu_集合()的组合来确定有多少个处理器可供选择 处理并调整JVMs os::active\u处理器\u计数 适当地。_CPU()的数量_将根据 cpu_quota()和cpu_period()使用以下公式:cpu的数量= cpu\u配额()/cpu\u期间()。如果cpu_共享已设置为 容器中,将根据 cpu_共享()/1024。1024是的默认和标准单位 计算基于云的容器管理中的相对cpu使用率 软件

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

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

在java8版本<191:cpu_shares()/1024=256/1024=上标识为2

在java8 version>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支持等)