为什么 Docker 会出现 OOM?

Why do I get OOM with Docker?

我有 Java 个应用程序,打包到 Docker 中并托管在 Amazon ECS 上。

主要技术有:

应用程序每隔 1-2 天就会崩溃并再次被亚马逊服务唤醒。

在Docker虫下我找到了原因:

"OOMKilled": true,

我将执行器连接到 CloudWatch,我发现内存消耗图有奇怪的行为:

那些蓝色的峰值是应用程序崩溃的时刻。

我读到 Java 8 在正确读取主机最大内存方面存在一些问题但是:

1) Docker 以应该可以解决问题的标志开始

ENTRYPOINT exec java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -Xms300M -XX:PermSize100M -Djava.security.egd=file:/dev/./urandom -jar /app.jar

2) 无论如何 VM 有 4Gb 内存,所以 ~1.3Gb 峰值很高,不应该杀死应用程序。

3) 在高峰时刻服务器上没有任何显着负载

-XX:PermSize100M

不适用于 java 8.

-XX:MaxRAMFraction=1

这告诉 JVM java 对象 的 托管堆的最大值是所有可用内存。但是 JVM 分配的内存不仅仅是 java 个对象。例如。元空间、打开文件的字节缓冲区、加载的本机库等。

您应该改为执行以下操作之一:

  • 使用 MaxRAMFraction=2 而不是 1
  • 手动将 Xmx 设置为低于可用内存的值
  • 升级到 java >= 11 并使用 MaxRAMPercentage 进行更精细的控制
  • 启用交换让额外的内存溢出到磁盘

有关较新的 java 版本的更多信息,另请参阅