Java in Docker and Kubernetes,运行在Docker或者Kubernetes中的JAVA程序如何正确获取CPU和内存的限制

2,006 阅读1分钟
参考网址
https://www.ipcpu.com/2019/03/java-in-docker-and-kubernetes/

概述

Docker容器利用CGroup对进程使用的资源进行限制,而在容器中的JVM依然会利用宿主机环境的内存大小和CPU核数进行缺省设置,这导致了JVM Heap的错误计算。JVM缺省的GC、JIT编译线程数量取决于宿主机CPU核数。如果我们在一个节点上运行多个Java应用,即使我们设置了CPU的限制,应用之间依然有可能因为GC线程抢占切换,导致应用性能受到影响。 那么我们来看下各个版本JDK如何使用docker的限制。

一、JDK老版本

1、使用环境变量,直接指定JVM堆大小 -e JAVA_OPTIONS=’xMX300m’
2、明确GC和JIT并行线程数目,以避免二者占用过多资源。

-XX:ParallelGCTreads
-XX:CICompilerCount

注意ParallelGCThreads的计算方法:

ParallelGCThreads = (ncpus <= 8) ? ncpus : (8 + ((ncpus - 8) * 5) / 8);
#cpu核数小于等于8,取核数;cpu核数大于8按后面公式计算

二、JDK 8u131+(backported)

使用以下JVM参数,适配docker容器的内存,CPU可能无法获取限制,需要手动设置

-XX:+UnlockExperimentalVMOptions 
-XX:+UseCGroupMemoryLimitForHeap

三、 JDK 8u191+(backported)

默认开启了UseContainerSupport,支持容器内部获取CPU和内存限制。

-XX:UseContainerSupport

并增加了ActiveProcessorCount参数指定CPU数量

-XX:ActiveProcessorCount=count

四、 JDK9 、JDK10

不是LTS(长期支持)版本

五、 JDK11+

默认开启了UseContainerSupport,支持容器内部获取CPU和内存限制。

-XX:UseContainerSupport

并增加了ActiveProcessorCount参数指定CPU数量

-XX:ActiveProcessorCount=count