| 副标题[/!--empirenews.page--]   前言 Java与Docker的结合,虽然更好的解决了application的封装问题。但也存在着不兼容,比如Java并不能自动的发现Docker设置的内存限制,CPU限制。 这将导致JVM不能稳定服务业务!容器会杀死你JVM进程,而健康检查又将拉起你的JVM进程,进而导致你监控你的pod一天重启次数甚至能达到几百次。 我们希望当Java进程运行在容器中时,java能够自动识别到容器限制,获取到正确的内存和CPU信息,而不用每次都需要在kubernetes的yaml描述文件中显示的配置完容器,还需要配置JVM参数。 使用JVM MaxRAM参数或者解锁实验特性的JVM参数,升级JDK到10+,我们可以解决这个问题(也许吧~.~)。 首先Docker容器本质是是宿主机上的一个进程,它与宿主机共享一个/proc目录,也就是说我们在容器内看到的/proc/meminfo,/proc/cpuinfo  与直接在宿主机上看到的一致,如下。 Host cat /proc/meminfo  MemTotal: 197869260 kB MemFree: 3698100 kB MemAvailable: 62230260 kB 
 容器 docker run -it --rm alpine cat /proc/meminfo MemTotal: 197869260 kB MemFree: 3677800 kB MemAvailable: 62210088 kB 
 那么Java是如何获取到Host的内存信息的呢?没错就是通过/proc/meminfo来获取到的。 默认情况下,JVM的Max Heap Size是系统内存的1/4,假如我们系统是8G,那么JVM将的默认Heap≈2G。 Docker通过CGroups完成的是对内存的限制,而/proc目录是已只读形式挂载到容器中的,由于默认情况下Java  压根就看不见CGroups的限制的内存大小,而默认使用/proc/meminfo中的信息作为内存信息进行启动,  这种不兼容情况会导致,如果容器分配的内存小于JVM的内存,JVM进程会被理解杀死。 内存限制不兼容 我们首先来看一组测试,这里我们采用一台内存为188G的物理机。 #free -g total used free shared buff/cache available Mem: 188 122 1 0 64 64 
 以下的测试中,我们将包含openjdk的hotspot虚拟机,IBM的openj9虚拟机。 以下测试中,我们把正确识别到限制的jdk,称之为安全(即不会超出容器限制不会被kill),反之称之为危险。 测试用例1(OPENJDK) 这一组测试我们使用最新的openjdk8-12,给容器限制内存为4G,看JDK默认参数下的最大堆为多少?看看我们默认参数下多少版本的JDK是安全的 命令如下,如果你也想试试看,可以用一下命令。 docker run -m 4GB --rm openjdk:8-jre-slim java -XshowSettings:vm -version docker run -m 4GB --rm openjdk:9-jre-slim java -XshowSettings:vm -version docker run -m 4GB --rm openjdk:10-jre-slim java -XshowSettings:vm -version docker run -m 4GB --rm openjdk:11-jre-slim java -XshowSettings:vm -version docker run -m 4GB --rm openjdk:12 java -XshowSettings:vm -version 
 OpenJDK8(并没有识别容器限制,26.67G) 危险 [root@xiaoke-test ~]# docker run -m 4GB --rm openjdk:8-jre-slim java -XshowSettings:vm -version VM settings:  Max. Heap Size (Estimated): 26.67G  Ergonomics Machine Class: server  Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode) 
 OpenJDK8 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap  (正确的识别容器限制,910.50M)安全 [root@xiaoke-test ~]# docker run -m 4GB --rm openjdk:8-jre-slim java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XshowSettings:vm -version VM settings:  Max. Heap Size (Estimated): 910.50M  Ergonomics Machine Class: server  Using VM: OpenJDK 64-Bit Server VM openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode) 
 (编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |