出品丨Docker公司(ID:docker-cn)
編譯丨小東
每周一、三、五,與您不見不散!
隨著2018年的結(jié)束,我們將回顧排名前五的最受讀者歡迎的文章。今天分享的第一篇文章,將幫助那些在容器中運(yùn)行 Java 虛擬機(jī)(JVM)時(shí)遇到內(nèi)存和 CPU
大小調(diào)整/使用困難的人,本文將解釋如何在 Docker Desktop(Mac或Windows)和 Docker Enterprise 環(huán)境中改進(jìn)
Docker 容器與 Java 10的集成。
許多應(yīng)用程序都以容器的形式運(yùn)行在 Java 虛擬機(jī)(JVM)中,其中包括 Apache Spark 和 Kafka
等數(shù)據(jù)服務(wù)以及舊的企業(yè)級(jí)應(yīng)用程序。直到最近,在容器中運(yùn)行 Java 虛擬機(jī)會(huì)出現(xiàn)內(nèi)存和cpu大小以及使用方面的問題,從而導(dǎo)致性能損失。這是因?yàn)?Java
沒有識(shí)別到它是在容器中運(yùn)行的。隨著 Java 10的發(fā)布,Java 虛擬機(jī)現(xiàn)在可以識(shí)別容器控制組(cgroups)設(shè)置的約束。內(nèi)存和 cpu
約束都可以用于直接在容器中管理 Java 應(yīng)用程序,包括:
* 遵守容器中設(shè)置的內(nèi)存限制;
* 在容器中設(shè)置可用的 cpu;
* 在容器中設(shè)置 cpu 約束;
Docker Desktop(Mac 或 Windows)和 Docker Enterprise 環(huán)境都實(shí)現(xiàn)了 Java 10的改進(jìn)。
容器內(nèi)存限制
在 Java 9之前,Java 虛擬機(jī)無法識(shí)別容器使用標(biāo)記設(shè)置的內(nèi)存或CPU限制。在Java 10中,內(nèi)存限制將自動(dòng)進(jìn)行識(shí)別并強(qiáng)制執(zhí)行。
Java 將服務(wù)器類機(jī)器定義為具有2個(gè) CPU 和 2GB 內(nèi)存,默認(rèn)堆大小為物理內(nèi)存的1/4。 例如,Docker Enterprise Edition
安裝有2GB內(nèi)存和4個(gè)CPU。比較運(yùn)行 Java 8和 Java 10之間容器的區(qū)別。首先,Java 8:
docker container run -it -m512 --entrypoint bash openjdk:latest $
docker-java-home/bin/java -XX:+PrintFlagsFinal -version | grep MaxHeapSize
uintx MaxHeapSize := 524288000 {product} openjdk version "1.8.0_162"
最大堆大小為 512M 或 Docker EE 安裝設(shè)置的 2GB 的1/4,而不是容器上設(shè)置的限制為512M。 相比之下,在 Java
10上運(yùn)行相同的命令表明容器中設(shè)置的內(nèi)存限制非常接近預(yù)期的128M:
docker container run -it -m512M --entrypoint bash openjdk:10-jdk $
docker-java-home/bin/java -XX:+PrintFlagsFinal -version | grep MaxHeapSize
size_t MaxHeapSize = 134217728 {product} {ergonomic} openjdk version "10"
2018-03-20
設(shè)置可用的CPU
默認(rèn)情況下,每個(gè)容器對(duì)主機(jī) CPU 周期的訪問權(quán)限是不受限制的??梢栽O(shè)置各種約束來限制給定容器對(duì)主機(jī) CPU 周期的訪問。Java 10可以識(shí)別出這些限制:
docker container run -it --cpus 2 openjdk:10-jdk jshell>
Runtime.getRuntime().availableProcessors() $1 ==> 2
分配給 Docker EE 的所有 CPU 獲得相同比例的 CPU 周期。可以通過相對(duì)于所有其他正在運(yùn)行的容器的權(quán)重更改容器的 CPU
份額權(quán)重來修改該比例。該比例僅適用于 CPU 密集型進(jìn)程運(yùn)行時(shí)。當(dāng)一個(gè)容器中的任務(wù)空閑時(shí),其他容器可以使用剩余的 CPU 時(shí)間。 實(shí)際的 CPU
時(shí)間量將根據(jù)系統(tǒng)上運(yùn)行的容器數(shù)量而有所不同。這些可以在 Java 10中進(jìn)行設(shè)置:
docker container run -it --cpu-shares 2048 openjdk:10-jdk jshell>
Runtime.getRuntime().availableProcessors() $1 ==> 2
“cpuset” 約束設(shè)置了哪些 cpu 允許在 Java 10中執(zhí)行。
docker run -it --cpuset-cpus="1,2,3" openjdk:10-jdk jshell>
Runtime.getRuntime().availableProcessors() $1 ==> 3
分配內(nèi)存和 CPU
使用 Java 10,容器設(shè)置可用于估計(jì)部署應(yīng)用程序所需的內(nèi)存和 CPU 分配。假設(shè)已經(jīng)確定了容器中運(yùn)行的每個(gè)進(jìn)程的內(nèi)存堆和 CPU 需求,并設(shè)置了
JAVA_OPTS。例如,如果您的應(yīng)用程序分布在10個(gè)節(jié)點(diǎn)上,五個(gè)節(jié)點(diǎn)需要512Mb內(nèi)存,每個(gè)節(jié)點(diǎn)占用 1024
CPU,另外五個(gè)節(jié)點(diǎn)需要256Mb內(nèi)存,每個(gè)節(jié)點(diǎn)占用 512 CPU共享。請(qǐng)注意,1個(gè)CPU份額比例由 1024 表示。
對(duì)于內(nèi)存,應(yīng)用程序至少需要分配 5Gb 內(nèi)存。
* 512Mb x 5 = 2.56 Gb
* 256Mb x 5 = 1.28 Gb
對(duì)于 CPU,應(yīng)用程序需要分配8個(gè)CPU才能高效運(yùn)行。
* 1024 x 5 = 5 CPUs
* 512 x 5 = 3 CPUs
最佳實(shí)踐建議:分析應(yīng)用程序以確定 Java 虛擬機(jī)中運(yùn)行的每個(gè)進(jìn)程的內(nèi)存和 CPU 分配。無論如何,Java 10在調(diào)整容器大小時(shí)消除了猜測,預(yù)防了
Java 應(yīng)用程序中的內(nèi)存不足錯(cuò)誤以及保障了分配足夠的 CPU 來處理工作負(fù)載。
熱門工具 換一換