记一次OutOfMemory定位过程-续

在前文《记一次OutOfMemory定位过程》完成时最终也没有定位到ECS 中JVM Heap size没法控制的缘由,今天再次尝试终于有了一些线索,翻查了ECS的部署脚本发现了memoryReservation参数,根据Amazon Elastic Container Service任务定义参数的定义,它对应的是docker run的--memory-reservation选项,该参数是一个软控制,实限上内存使用是能够超过该限制的,因而把它修改成memory,同时推送一个新的image并部署html

ENTRYPOINT exec java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XshowSettings:vm -jar app.jar

task启动后输出,结果以下:java

VM settings:
Max. Heap Size (Estimated): 3.56G
Ergonomics Machine Class: server
Using VM: OpenJDK 64-Bit Server VM

此次的Heap size终于看上去像是想要的,只是不幸的是在程序维持繁忙状态约半小时后,再次由于一样的缘由被关闭docker

Status reason   OutOfMemoryError: Container killed due to memory usage
Exit Code   137

查看其中一个task最后的GC日志app

2018-06-07T07:57:55.742+0000: [GC (Allocation Failure) [PSYoungGen: 1013313K->121010K(1150464K)] 3324353K->2449342K(3730944K), 0.3680289 secs] [Times: user=0.37 sys=0.04, real=0.36 secs]
2018-06-07T07:58:01.582+0000: [GC (Allocation Failure)

JVM Heap size直到最后都并无超限,也许XX:MaxRAMFraction=2能够解决这个问题,可是内存使用率又过低,故最终仍是决定使用ide

ENTRYPOINT exec java -Xmx3072m -Xms3072m -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XshowSettings:vm -jar app.jar

把内存使用率控制在75%,运行近三小时没有再出现问题。ui

结语

  • 前一次使用-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1时,JVM没法根据Docker容器的内存设置最大Heap size是由于ECS的参数选得不对,致使Docker内存设置不正确
  • 当Docker内存设置正确,JVM heap size 100%占用Docker可用内存时仍然可能出现OutOfMemory,这应该与JVM或Docker无关,而是ECS的内存限制机制引发的,既然如此,那么用Xmx/Xms控制内存也是个不错的选择
相关文章
相关标签/搜索