我在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
答案 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支持等)