为什么 Docker 会出现 OOM?
Why do I get OOM with Docker?
我有 Java 个应用程序,打包到 Docker 中并托管在 Amazon ECS 上。
主要技术有:
- SpringBoot 2
- Java 8
- 具有 4Gb 内存的 EC2 虚拟机
应用程序每隔 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 版本的更多信息,另请参阅 。
我有 Java 个应用程序,打包到 Docker 中并托管在 Amazon ECS 上。
主要技术有:
- SpringBoot 2
- Java 8
- 具有 4Gb 内存的 EC2 虚拟机
应用程序每隔 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 版本的更多信息,另请参阅