如不雅你测验测验在容器中运行Java法度榜样,或者专注于Docker,你可能会碰到一些关于JVM和堆大年夜小的问题。本篇文┞仿将介绍若何解决这些问题。
- $ docker logs mycontainer150|grep -i MaxHeapSize
- uintx MaxHeapSize := 262144000 {product}
很多开辟者会(或者应当)知道,当我们为运行在Linux容器(docker, rkt, runC, lxcfs, etc,)中的Java法度榜样去设置JVM的GC、堆大年夜小和运行时编译器的参数时并没有获得预想的效不雅。当我们经由过程“java -jar mypplication-fat.jar”的方法而不设置任何参数来运行一个Java应用时,JVM会根据自身典范多参数进行调剂,以便在履行情况中获得最优的机能。
本篇博客精晓过简单的方法向开辟人员展示在将Java应用运行在Linux容器内时须要懂得的内容。
我们偏向于认为容器可以像虚拟机一样可以完全的定义虚拟机的CPU个数和虚拟机的内存。容器更像是一个过程级其余资本(CPU、内存、文件体系、收集等)隔离。这种隔离是依附于Linux内核中供给的一个 cgroups 的功能。
然而,一些可以大年夜运行时情况中收集信息的应用法度榜样在cgroups功能出现之前已经存在。在容器中履行敕令 ‘top‘, ‘free‘, ‘ps’,也包含没有经由优化的JVM是一个会受到高限制的Linux过程。让我们来验证一下。
问题
为了展示碰到的问题,我应用敕令“docker-machine create -d virtualbox –virtualbox-memory ‘1024’ docker1024”在虚拟机中创建了一个具有1GB内存的Docker守护过程,接下来在3个Linux容器中履行敕令“free -h”,使其只有100MB的内存和Swap。结不雅显示所有的容器总内存是995MB。
即使是在 Kubernetes/OpenShift集群中,结不雅也是类似的。我在一个内存是15G的集群中也履行了敕令使得Kubernetes Pod有511MB的内存限制(敕令:“kubectl run mycentos –image=centos -it –limits=’memory=512Mi’”),总内存显示为14GB。
想要知道为什么是如许的结不雅,可以去浏览此篇博客文┞仿 “ Memory inside Linux containers – Or why don’t free and top work in a Linux container? ”
我们须要知道Docker参数 (-m, –memory和–memory-swap)和Kubernetes参数 (–limits)会让Linux内核在一个过程的内存超出限制时将其Kill掉落,然则JVM根本不清跋扈这个限制的存在,当跨越这个限制时,不好的工作产生了!
为了模仿当一个过程超出内存限制时会被杀逝世的场景,我们可以经由过程敕令“docker run -it –name mywildfly -m=50m jboss/wildfly”在一个容器中运行WildFly Application Server并且为其限制内存大年夜小为50MB。在这个容器运行时代,我们可以履行敕令“docker stats”来查看容器的限制。
然则过了几秒之后,容器Wildfly将会被中断并且输出信息:*** JBossAS process (55) received KILL signal ***
经由过程敕令 “docker inspect mywildfly -f ‘{{json .State}}'”可以查看容器被杀逝世的原因是产生了OOM(内存不足)。容器中的“state”被记录为OOMKilled=true 。
这将如何影响Java应用
在Docker宿主机中创建一个具有1GB内存的虚拟机(在之前应用敕令已经创建完毕 “docker-machine create -d virtualbox –virtualbox-memory ‘1024’ docker1024”) ,并且限制一个容器的内存为150M,看起来已经足够运行这个在 Dockerfile中设置过参数-XX: PrintFlagsFinal 和 -XX: PrintGCDetails的Spring Boot application了。这些参数使得我们可以攫取JVM的初始化参数并且获得 Garbage Collection (GC)的运行具体情况。
- $ docker run -it --rm --name mycontainer150 -p 8080:8080 -m 150M rafabene/java-container:openjdk
我也供给了一个拜访接口“/api/memory/”来应用String对象加载JVM内存,模仿大年夜量的消费内存,可声调用处尝:
- $ curl http://X 41X:8080/api/memory
推荐阅读
在以前的几年中,软件定义收集大年夜收集世比赛脱颖而出。但企业并在采取SDN技巧上颇为迟疑,究其原因是实施SDN所花费的时光和精力成本相比,它带来的优势尚不足为道。然而,跟着技巧和R>>>详细阅读
本文标题:在Docker中运行Java:为了防止失败,你应该知道的
地址:http://www.17bianji.com/lsqh/34804.html
1/2 1