Docker 镜像 JVM 调优

当我们使用Java环境基础镜像的时候,期望在启动 Docker 镜像的时候对JVM参数进行一定的调优,通常要么是启动的时候写死优化变量,但是这种方式不方便,还有就通过自定义环境变量JAVA_OPTS或者使用JAVA_TOOL_OPTIONS方式。

基于 JAVA_OPTS 环境变量(不推荐)

此方式需要 在 Dockerfile 中定义变量 JAVA_OPTS,并在启动命令中使用 JAVA_OPTS

Dockerfile 示例:

#FROM openjdk:11-jre-alpine
#FROM openjdk:11-jre-slim
#FROM openjdk:11-jdk-alpine
#FROM openjdk:11-jdk-slim
#FROM openjdk:11-jdk-oracle
#FROM openjdk:8-jre-alpine
#FROM openjdk:8-jre-slim
#FROM openjdk:8-jdk-alpine
#FROM openjdk:8-jdk-slim
#FROM openjdk:8-jdk-oracle

FROM openjdk:8-jdk-alpine

# 申明临时卷
VOLUME /logs
VOLUME /tmp

# 拷贝本地Jar包到根目录
ADD ./target/app.jar /

# 暴露端口
# EXPOSE 8100

#设置变量 JAVA_OPTS
ENV JAVA_OPTS="" #这样写会以shell方式执行,会替换变量

# 挂着启动脚本
ENTRYPOINT java ${JAVA_OPTS} -jar app.jar
#下面这样写法不行,他只是拼接不会识别变量
#ENTRYPOINT ["java", "${JAVA_OPTS}", "-jar","app.jar"]

然后;运行 docker run 命令;运行时通过-e重置覆盖环境变量中JAVA_OPTS参数信息。

docker run  -e  JAVA_OPTS='-Xmx1344M -Xms1344M -Xmn448M -XX:MaxMetaspaceSize=192M -XX:MetaspaceSize=192M'

进入容器

docker exec -it 容器ID/名称 /bin/bash

查看java应用,就可以看到

ps -ef | grep java

结果如下:

/myapp # ps -ef|grep java1 root 2:49 java -Xmx1344M -Xms1344M -Xmn448M -XX:MaxMetaspaceSize=192M -XX:MetaspaceSize=192M -Djava.security.egd=file:/dev/./urandom -jar /app.jar466 root 0:00 grep java

基于 JAVA_TOOL_OPTIONS 环境变量(推荐)

JAVA_TOOL_OPTIONS 就是个环境变量,它会被JNI API的JNI_CreateJavaVM函数使用。因为JAVA_TOOL_OPTIONS是被被JNI_CreateJavaVM调用的,顾名思义是创建VM

各种OPTIONS的区别:

也许你经常遇到JAVA_OPTS、JAVAOPTIONS和JAVA_TOOL_OPTIONS,那么他们有什么不同呢?

  • JAVA_OPTS:常用于一些应用的配置,如Tomcat,但它一般不作为环境变量,也不能被JVM识别的,是那些应用的自定义配置;

  • JAVAOPTIONS:也是作为环境变量来替代命令行参数的,但它是JVM厂家自定义的,可以覆盖JAVA_TOOL_OPTIONS,但各厂家的不同,JAVAOPTIONS是Oracle的JVM,而IBM的则是用IBM_JAVA_OPTIONS。

  • JAVA_TOOL_OPTIONS:是标准的,所有虚拟机都能识别和应用的。

https://www.jb51.net/article/207937.htm

            - name: JAVA_TOOL_OPTIONS
              value: '-Xms256M -Xmx512M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:GCLogFileSize=20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/heaperror.log -Xloggc:/logs/gcerror.log'

分配内存 堆配置推荐


1G -Xmx512M -Xms512M -Xmn256M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=64M

2G -Xmx1344M -Xms1344M -Xmn448M -XX:MaxMetaspaceSize=192M -XX:MetaspaceSize=192M

3G-Xmx2048M -Xms2048M -Xmn768M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M

4G-Xmx2688M -Xms2688M -Xmn960M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M

5G-Xmx3392M -Xms3392M -Xmn1216M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M

6G-Xmx4096M -Xms4096M -Xmn1536M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M

7G-Xmx4736M -Xms4736M -Xmn1728M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M

8G-Xmx5440M -Xms5440M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:GCLogFileSize=20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/heaperror.log -Xloggc:/logs/gcerror.log

“-XX:InitiatingHeapOccupancyPercent=60”, “-XX:MinHeapDeltaBytes=262144”, “-XX:MetaspaceSize=128m”, “-XX:MaxMetaspaceSize=256m”, “-XX:InitialHeapSize=256M”, “-XX:MaxHeapSize=256M”, “-XX:+PrintGCDetails”, “-XX:+PrintGCTimeStamps”, “-XX:+UseG1GC”, “-XX:GCLogFileSize=20m”, “-XX:+HeapDumpOnOutOfMemoryError”, “-XX:HeapDumpPath=/logs/heaperror.log”, “-Xloggc:/logs/gcerror.log”,

  • 2核4G
-Xms2048m -Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseGCLogFileRotation -XX:HeapDumpPath=/home/admin/edas-container/logs/oom.log -XX:ParallelGCThreads=4 -XX:MaxMetaspaceSize=512m -Xloggc:/home/admin/edas-container/logs/ -XX:NumberOfGCLogFiles=30 -XX:+PrintGCDateStamps -XX:GCLogFileSize=100m -XX:MetaspaceSize=512m -XX:+UseConcMarkSweepGC -XX:+PrintGC
  • 4核8G
-Xms5120m -Xmx5120m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseGCLogFileRotation -XX:HeapDumpPath=/home/admin/edas-container/logs/oom.log -XX:ParallelGCThreads=4 -XX:MaxMetaspaceSize=512m -XX:NewSize=512m -Xloggc:/home/admin/edas-container/logs/ -XX:NumberOfGCLogFiles=30 -XX:+PrintGCDateStamps -XX:GCLogFileSize=1024m -XX:MetaspaceSize=512m -XX:+UseConcMarkSweepGC -XX:+PrintGC
            - name: JAVA_TOOL_OPTIONS
              value: >-
                -Xmx4096M -Xms4096M -Xmn1536M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M -XX:MetaspaceSize=256M
                -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
                -XX:+UseG1GC -XX:MaxGCPauseMillis=200m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
                -XX:GCLogFileSize=20m -XX:+HeapDumpOnOutOfMemoryError
                -XX:HeapDumpPath=/logs/heaperror.log
                -Xloggc:/logs/gcerror.log

常用的JVM配置参数有哪些?

-Xms:初始大小内存,默认为物理内存的1/64等价于-XX:InitialHeapSize

-Xmx:最大分配内存,默认为物理内存的1/4等价于-XX:MaxHeapSize

-Xss:设置单个线程栈的大小,一般默认为512k~1024k等价于-XX:ThreadStackSize
    当值等于0的时候,代表使用得是默认大小

-Xmn:设置年轻代大小

-XX:MetaspaceSize:设置元空间大小(元空间与永久代最大的区别为:元空间并不在虚拟机中,而使用的是本地内存,因此,元空间只收本地内存的限制)
    手动设置:-XX:MetaspaceSize=1024m

典型设置案例

-XX:+PrintGCDetails:输出详细GC收集日志信息

当堆内存不够的话,会爆出OOM错误

-XX:SurvivorRatio:设置新生代中 eden 和 S0/S1 空间比例,默认 -XX:SurvivorRatio=8,Eden : S0 : S1 = 8 : 1 : 1

​ -XX:SurvivorRatio=4==》Eden : S0 : S1 = 4 : 1 : 1

-XX:NewRatio:配置年轻代和老年代在堆结构的占比,默认 -XX:NewRatio=2 新生代占1,老年代占2,年轻代占整个堆的 1/3

​ -XX:NewRatio=4 新生代占1,老年代占4,年轻代占整个堆的 1/5

-XX:MaxTenuringThreshold:设置垃圾最大年龄。默认是15。

-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入老年代。对于老年代比较多的应用,可以提高效率。如果此值设置为一个较大的值,则年前对象会在Survivor区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代被回收的概率!

在这里插入图片描述

因为是由四位二进制数组成,所以垃圾最大年龄为15.因为0-15是16个数字

作者:Jeebiz  创建时间:2023-02-12 01:48
最后编辑:Jeebiz  更新时间:2024-08-02 14:21