一、背景
对于 Java8 的一些较早的版本(8u131 以前?),如果部署在 docker 容器中,因为 JVM 不能感知到 docker 容器的资源限度,会导致 docker 编排文件中设置的资源限度对 JVM 有效。轻则多个 docker 容器抢占资源导致性能降落,重则 docker 容器不稳固频频重启。
在 Java8 8u131+ 和 JDK9 当前,JVM 减少了感知容器资源的参数,解决了这个问题。
本文以 JDK11 为例,阐明如何设置 java 利用的容器感知参数,以及如何在 docker 编排文件中设置容器资源限度。
二、环境
- java: AdoptOpenJDK 11.0.8+10
- docker ce: 19.03.4
- docker-compose: 1.24.0
三、Java 利用相干设置
制作一个基于 openjdk11 的 java 利用镜像。
3.1 Java 根底镜像
本文基于 AdoptOpenJDK 的 openjdk11 镜像 adoptopenjdk/openjdk11:jdk-11.0.8_10-alpine
制作了中国时区,反对中文的 openjdk11 镜像。
Dockerfile 如下:
# 从 dockerhub 拉取根底镜像
FROM adoptopenjdk/openjdk11:jdk-11.0.8_10-alpine
# 设置时区与语言环境变量
ENV TIME_ZONE=Asia/Shanghai \
LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8 \
LC_ALL=en_US.UTF-8
# 执行以下命令设置时区
RUN apk add --no-cache tzdata \
&& echo "${TIME_ZONE}" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime
在 Dockerfile 所在目录执行 docker 镜像编译命令:docker build -t < 自定义镜像名 >:<tag> .
,如:
docker build -t czhao/base-openjdk11:jdk-11.0.8_001 .
3.2 Java 利用
当时筹备一个 openjdk11 开发的 java 利用,编译为 jar,基于后面的 Java 根底镜像,编译 java 利用镜像。
Dockerfile 如下:
FROM czhao/base-openjdk11:jdk-11.0.8_001
# JDK11 反对: -XX:+UseContainerSupport 使 JVM 可能感知容器资源,-XX:InitialRAMPercentage 初期容器内存占比,-XX:MaxRAMPercentage 最大容器内存占比
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:InitialRAMPercentage=50 -XX:MaxRAMPercentage=80"
# 复制上下文目录下的 target/*.jar 到容器里
ADD target/*.jar app.jar
# 指定容器启动程序及参数 <ENTRYPOINT> "<CMD>"
ENTRYPOINT java ${JAVA_OPTS} -jar /app.jar
-XX:+UseContainerSupport
开启容器感知。-XX:InitialRAMPercentage
与-XX:MaxRAMPercentage
用于设置 JVM 初始的容器内存占比和最大容器内存占比。- 上述命令仅在 java10 当前无效,其余反对感知的版本的参数配置各不相同。
- 镜像编译命令不再赘述。
四、docker 编排与启动
编排 java 利用的 docker compose 文件,启动,并查看资源占用。
4.1 docker 编排文件
这里应用 docker compose v3 的编排规定,编排文件如下:
service.yaml:
version: '3'
...
services:
<java 利用名 >:
container_name: <java 利用名 >
image: <java 利用镜像名 >:<java 利用镜像标签 >
...
deploy:
resources:
limits:
cpus: '1.00'
memory: 1024M
reservations:
# cpus: '0.1'
memory: 512M
- deploy 原本是 docker swarm 的
docker stack deploy
命令才反对的属性,但能够在docker-compose up
命令中通过增加--compatibility
参数使之失效。但deploy.resources.reservations.cpus
依然无奈失效。- limits 是资源下限,reservations 是保留资源。
- cpus 设置的数字是占用宿主机 cpu 的比例,
1.00
即100%
,代表齐全占用了宿主机 CPU 的一个 process。留神,宿主机如果是多核机器的话,100%
只是占用了一个 process 而已。例如一个8 core 16 process
的宿主机,cpus 实践上能够设置到16.00
。但这里倡议一个容器的 cpu 占用不要超过1.00
。
4.2 启动 docker 容器并查看资源占用
应用以下命令启动:
docker-compose --compatibility -f service.yaml up -d
而后应用以下命令,查看 docker 容器的资源占用状况:
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
docker 资源占用如下:
NAME CPU % MEM USAGE / LIMIT
<java 利用名 > 0.66% 418.5MiB / 1GiB
留神察看就能够发现,该容器占用 CPU 最高在 100% 左右,而内存则不会超过 1G 的限度。