記一次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控制內存也是個不錯的選擇
相關文章
相關標籤/搜索