短短几年内,容器就改变了软件行业的面貌。也许您已经到了在容器中运行Java的地步。那很棒!不幸的是,关于容器化Java应用程序的CPU和内存使用率,还有一些事情要注意,我将在下面概述。安全
本文假定整体上熟悉Java和容器。若是您须要更多背景知识,请查看部分(或所有)参考资料。性能
若是有一个关于在容器中运行Java的关键声明,则为如下内容:spa
不要为在容器中运行的任何JAVA程序手动设置JVM堆空间。相反的是,设置容器限制。code
为何?进程
设置容器内存(和CPU)限制。仅依靠资源请求(软限制)是不够的。软限制很是适合帮助调度程序,可是设置硬限制可使Docker(或您使用的任何容器运行时)分配指定的资源给容器自己,而再也不分配更多资源。这也将容许Java(从Java 8u191开始默认为“容器感知”)根据放置在容器自己上的资源限制(而不是容器正在运行的节点)正确分配内存。内存
[Min | Max | Initial] RAMPercentage
参数在较新的Java版本中,引入了如下JVM参数(并将其反向移植到Java 8u191)。资源
-XX:MinRAMPercentage
-XX:MaxRAMPercentage
-XX:InitialRAMPercentage
我不会详细介绍它们是如何工做的,可是关键要点在于它们能够用于微调JVM堆大小,而无需直接设置堆大小。也就是说,容器仍然能够依靠施加在其上的限制。it
那么使用什么正确的值呢?答案是-“取决于”……尤为是对容器施加的限制。容器
默认状况下,JVM堆获取容器内存的25%。您能够调整初始/最小/最大堆参数来更改此…例如设置-XX:MaxRAMPercentage = 50将容许JVM为堆消耗50%的容器内存,而不是默认的25%。何时安全,很大程度上取决于容器必须使用多少内存以及容器中正在运行哪些进程。扩展
例如,若是您的容器正在运行一个Java进程,并为其分配了4 GB的RAM,而且您设置了-XX:MaxRAMPercentage = 50
,则JVM堆将得到2 GB。这与一般会得到的1 GB默认值相反。在这种状况下,几乎能够确定50%是绝对安全的,甚至是最佳的,由于许多可用RAM可能未获得充分利用。可是,假设同一容器仅分配了512 MB RAM。如今设置-XX:MaxRAMPercentage = 50
将为堆提供256 MB的RAM,而仅将其他256 MB留给整个容器的其他部分。该内存将须要由容器中运行的全部其余进程以及JVM Metaspace / PermGen等分配共享。在这种状况下,也许50%不太安全。
所以,我提一下几点建议:
这超出了本文的范围,但请放心,也能够对此进行调整,但可能不该该这样作。默认的JVM行为适用于大多数用例。若是您发现本身试图解决一个晦涩的内存问题,那么多是时候考虑摆弄JVM内存这个有些深奥的领域了,可是不然我将避免直接作任何事情。
这里没什么可作的。从Java 8u191开始,JVM默认状况下是“容器感知”的,而且能够正确解释CPU份额分配。尽管有一些细节值得咱们理解,因此除了在这里概述以外,我将指导您阅读这篇出色的文章,详细说明全部这些。
现代Java很是适合在容器环境中运行,可是每一个人都应该知道一些不太明显的细节,以确保他们从应用程序中得到最佳性能。我但愿这里提供的信息以及出色的参考资料能够帮助您实现这一目标。