我将裸机java应用程序(jar jdk8)移动到docker容器和DC / OS。我注意到码头工人的奇怪模式,我们将-XMX设置为32 gig并分配一个36 gig的docker容器。每隔几个小时左右,应用程序将在旧的内存分配中出现峰值,并且当GC尝试执行堆转储时,GC将陷入循环(最大CPU)。
我是否可以使用任何优化或事物来了解为什么在1-5秒间隔内我们的速度如此之快?使用Docker和JVM可能需要注意哪些问题?
我们正在使用默认GC
答案 0 :(得分:2)
仅供将来参考:
我们正在使用JDK 8,似乎Oracle刚刚添加了一些使用Docker的实验标志。我相信这个案例可能是在GC分配线程的时候,它并不尊重来自cgroup的docker线程数。实验性标志似乎已经解决了我们的问题"脱轨问题"
https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits
答案 1 :(得分:1)
通常你想用>避免这个巨大的应用程序如果您可以使用DC / OS等容器平台,则可以使用30GB内存并将应用程序拆分为更小的部件,同时减少内存需求。
一般来说,关于GC和堆大小:如果你有大堆,那么完整的GC可能需要很长时间。就个人而言,我经历了完整的GC冻结,最长可达一分钟或更长时间,其堆大小与您提到的30GB相当。
关于容器中的Java:JVM实际上需要的内存比使用-Xmx
配置的内存多。因此,如果在DC / OS(Marathon)应用程序中指定了2GB的内存限制,则无法设置-Xmx2G
,因为此内存限制是一个严格的限制。如果容器内的进程超出这些内存限制,容器将被终止。由于JVM将保留比配置-Xmx
临时更多的内存,因此很可能会发生这种情况。一般情况下,我建议使用大约75%的已配置内存作为-Xmx
的值。
您可以查看支持-XX:+UseCGroupMemoryLimits
的较新JRE版本。这是使用cgroup容器限制进行内存消耗的JRE标志,有关更多信息,请参阅https://developers.redhat.com/blog/2017/04/04/openjdk-and-containers/。