Docker 中的 Java 运行时内存限制配置

现在是2020年12月,在这个时间点 Java 在 Docker 容器中运行的内存限制已经有了明确的解决方案,此处做个记录。

JDK 10 引入了默认开启的参数 UseContainerSupport,同时这个特性也被 backport 到 JDK1.8 的 8u191 版本。也就是说 8u191 和更后面的 JDK 都可以通过开启 UseContainerSupport 来支持 cgroup 看到 cgroup 的内存限制。
再结合 MaxRAMPercentage 来动态算一个堆内存上限就足够了,这个值具体看服务用到的堆外内存和线程的使用量,一般无脑给个 75/80 都没问题。具体程序用多少内存合适,正确实践一定是先预估一个偏保守的值,在环境里跑一下,然后结合实际请求量和监控来持续调节 kubernetes/docker 的内存限制数值。

下面是个 spring boot(layered jar) 工程打包为镜像的 Dockerfile 示例

FROM openjdk:15
WORKDIR application

COPY ./dependencies/ ./
COPY ./spring-boot-loader/ ./
COPY ./snapshot-dependencies/ ./
COPY ./application/ ./

ENV JAVA_OPTS='-Dspring.application.name=my-demo \
-XX:+UseContainerSupport \
-XX:MaxRAMPercentage=75.0 '

ENTRYPOINT exec java $JAVA_OPTS org.springframework.boot.loader.JarLauncher

最后还要再额外留意下,自 jdk9 (8u131)开始,这些跟容器支持的参数有过几轮变迁。如果没有多关注 upstream 或者搜了国内 CSDN 低劣二手文,很容易被拐到坑里去,比如看到下面这些参数,基本都是废弃或用不到的,不用再理会:

UnlockExperimentalVMOptions
UseCGroupMemoryLimitForHeap
UseCGroupMemoryLimit
MaxRAMFraction
MaxRAM

—— 引用自:李飘柔 https://www.zhihu.com/question/315793102/answer/1639340828


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 nickchenyx@gmail.com

Title:Docker 中的 Java 运行时内存限制配置

Count:380

Author:nickChen

Created At:2020-12-25, 10:14:34

Updated At:2023-05-08, 23:27:10

Url:http://nickchenyx.github.io/2020/12/25/java-docker-setup/

Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.