如果应用所使用的 java 版本在 8及8以下, JVM 在没有认为设定 Xmx Xms 时, 会根据 宿主机的内存进行 JVM 的参数设置,这样就会导致很大的问题。

比如,如果你的宿主机内存在 8G, 你的容器设置为 1G,那么 JVM 根据你的宿主机内存,给到你应用 2G左右的堆内存,此时 JVM 会按照 2G 进行 GC,此时会出现 OOM ,而导致容器被 kill 的情况。

 

这一情况在此篇博客中有详细探讨:

《Kubernetes之路 1 - Java应用资源限制的迷思》

https://blog.csdn.net/maoreyou/article/details/80134303

 

解决办法有三种:

 

一、 手动指定 应用启动时的 JVM 参数:

JVM的参数指定可以参考这几篇文章:

1、 根据这篇中的参数进行初步设定

《关于JVM突破Docker内存限制的解决方案及JVM推荐配置》

https://blog.csdn.net/cy_7030/article/details/81536590

 

2、 根据这篇中的 JVM 参数调优方法,参考实际应用,重新调整 JVM 值:

《JVM内存设置多大合适?Xmx和Xmn如何设置?》

https://www.cnblogs.com/zhangfengshi/p/11343102.html

《JVM 调优总结》

https://www.cnblogs.com/diegodu/p/9849611.html

《 jstat命令查看jvm的GC情况 (以Linux为例)》

https://www.cnblogs.com/yjd_hycf_space/p/7755633.html

《jvm 性能调优工具之 jmap》

https://www.jianshu.com/p/a4ad53179df3

 

还需要注意: 如果你的 Docker 中启动 java 使用的是 sh 而非 /bin/bash ,java进程的 pid 是1,

会导致:

Unable to get pid of LinuxThreads manager thread

通过使用 /bin/bash 启动可以解决:

《jstack on alpine:Unable to get pid of LinuxThreads manager thread》

https://blog.csdn.net/xianzi1261618338/article/details/83382989

 

二、 使用 java9 及以上版本,使用 容器资源感知特性:

java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap …

 

三、 使用这位大神制作的 tomcat 8 自动感知 CGroup 的镜像:

参考:

《如何设置Docker容器中Java应用的内存限制》

https://yq.aliyun.com/articles/18037

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐