记一次OutOfMemory定位过程-续

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

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

task启动后输出,结果如下:

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

这次的Heap size终于看上去像是想要的,只是不幸的是在程序维持繁忙状态约半小时后,再次因为同样的原因被关闭

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

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

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可以解决这个问题,但是内存使用率又太低,故最终还是决定使用

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

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

结语

  • 前一次使用-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1时,JVM无法根据Docker容器的内存设置最大Heap size是因为ECS的参数选得不对,导致Docker内存设置不正确
  • 即便Docker内存设置正确了,也需要考虑JVM内存使用率的情况,Java 8可能无法达到使用率100%的理想状态,也许用Xmx/Xms来控制内存也是个不错的选择

猜你喜欢

转载自www.cnblogs.com/hiver/p/9152650.html
今日推荐