作家
登录

在Docker中运行Java:为了防止失败,你应该知道的

作者: 来源: 2017-04-17 14:05:57 阅读 我要评论

这个接口将会返回下面的信息 “Allocated more than 80% (219.8 MiB) of the max allowed JVM memory size (241.7 MiB)”

在这里我们至少有2个问题:

  • 为什么JVM会许可241.7MiB的最大年夜内容?
  • 如不雅容器已经限制了内存为150MB,为什么许可Java分派内存到220MB?

起首,我们应当从新懂得在 JVM ergonomic page 中所描述的 “maximum heap size”的定义,它将会应用1/4的物理内存。JVM并不知道它运行在一个容器中,所以它将被许可应用260MB的最大年夜堆大年夜小。经由过程添加容器初始化时的参数-XX: PrintFlagsFinal,我们可以检查这个参数的值。

其次,我们应当懂得当在docker敕令行中设置了 “-m 150M”参数时,Docker守护过程会限制RAM为150M并且Swap为150M。大年夜结不雅上看,一个过程可以分派300M的内存,说清楚明了为什愦我们的过程没有收到任何大年夜Kernel中发出的退出旌旗灯号。

更多的关于Docker敕令中内存限制 (–memory)和Swap (–memory-swap)的差别可以参考 这里 。

更多的内存是解决筹划吗?

假如我们将Docker Machine的内存大年夜1GB进步到8GB(应用敕令 “docker-machine create -d virtualbox –virtualbox-memory ‘8192’ docker8192”),并且创建的容器大年夜150M到800M:

  1. $ docker run -it --name mycontainer -p 8080:8080 -m 800M rafabene/java-container:openjdk 

此时应用敕令 “curl http://X 58X:8080/api/memory” 还不克不及返回结不雅,因为在一个拥有8GB内存的JVM情况中经由计算的MaxHeapSize大年夜小是2092957696(~ 2GB)。可以应用敕令“docker logs mycontainer|grep -i MaxHeapSize”查看。

应用将会测验测验分派跨越1.6GB的内存,当跨越了容器的限制(800MB的RAM 800MB的Swap),过程将会被kill掉落。

很明显当在容器中运行法度榜样时,经由过程增长内存和设置JVM的参数不是一个好的方法。当在一个容器中运行Java应用时,我们应当基于应用的须要和容器的限制来设置最大年夜堆大年夜小(参数:-Xmx)。

解决筹划是什么?

在Docker中运行Java:为了防止掉败,你应当知道的

在Dockerfile中稍作修改,为JVM指定扩大的情况变量。修改内容如下:

如今我们可以应用JAVA_OPTIONS的情况变量来设置JVM Heap的大年夜小。300MB看起来对应用足够了。稍后你可以查看日记,看到Heap的值是 314572800 bytes ( 300MBi)。

Docker下,可以应用“-e”的参数来设置情况变量进行切换。

  1. $ docker run -d --name mycontainer8g -p 8080:8080 -m 800M -e JAVA_OPTIONS='-Xmx300m' rafabene/java-container:openjdk-env  
  2. $ docker logs mycontainer8g|grep -i MaxHeapSize  
  3. uintx MaxHeapSize := 314572800 {product} 

在Kubernetes中,可以应用“–env=[key=value]”来设置情况变量进行切换:

  1. CMD java -XX: PrintFlagsFinal -XX: PrintGCDetails $JAVA_OPTIONS -jar java-container.jar 
  1. $ kubectl run mycontainer --image=rafabene/java-container:openjdk-env --limits='memory=800Mi' --env="JAVA_OPTIONS='-Xmx300m'"   
  2. $ kubectl get pods   
  3. NAME READY STATUS RESTARTS AGE    
  4. mycontainer-2141389741-b1u0o 1/1 Running 0 6s    
  5. $ kubectl logs mycontainer-2141389741-b1u0o|grep MaxHeapSize    
  6. uintx MaxHeapSize := 314572800 {product}  

还能再改进吗?

有什么办法可以根据容器的限制来主动计算Heap的值?

事实上如不雅你的基本Docker镜像应用的是由Fabric8供给的,那么就可以实现。镜像fabric8/java-jboss-openjdk8-jdk应用了脚本来计算容器的内存限制,并且应用50%的内存作为上限。也就是有50%的内存可以写入。你也可以应用这个镜像来开/关调试、诊断或者其他更多的工作。让我们看一下一?Spring Boot应用的 Dockerfile :

  1. FROM fabric8/java-jboss-openjdk8-jdk:1.2.3  

      推荐阅读

      四步奠定SDN部署基石

    在以前的几年中,软件定义收集大年夜收集世比赛脱颖而出。但企业并在采取SDN技巧上颇为迟疑,究其原因是实施SDN所花费的时光和精力成本相比,它带来的优势尚不足为道。然而,跟着技巧和R>>>详细阅读


    本文标题:在Docker中运行Java:为了防止失败,你应该知道的

    地址:http://www.17bianji.com/lsqh/34804.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)