如何對 Amazon ECS 中的 OutOfMemory 錯誤進行疑難排解?

2 分的閱讀內容
0

我的 Amazon Elastic Container Service (Amazon ECS) 任務有記憶體使用量問題。或者,我的容器由於 OutofMemory 錯誤而退出。

簡短描述

如果您遇到記憶體不足的問題,Amazon ECS 會停止任務,並且您將收到以下錯誤訊息:

「OutOfMemoryError: 容器因記憶體使用量過大而終止」。

當容器程序所使用的記憶體量超過您在任務定義中分配的記憶體量時,就會出現此問題。若要解決 OutofMemory 問題,請執行下列疑難排解動作。

解決方法

識別 Amazon ECS 因記憶體耗盡而終止的任務

若要識別 Amazon ECS 因記憶體耗盡而終止的任務,請完成以下步驟:

  1. 在 Amazon ECS 主控台上查看已停止的任務
  2. 尋找退出代碼為 137139 的任務,這些任務通常在 Amazon ECS 遇到記憶體相關失敗時發生。
  3. 如果發現記憶體問題,請檢查容器代理程式日誌,看是否存在導致任務停止的堆積記憶體不足問題。

監控並分析容器記憶體使用情況

若要對記憶體相關應用程式問題進行疑難排解,請使用 Amazon CloudWatch Logs 分析您的任務。使用 Amazon ECS 或 CloudWatch 主控台監控服務記憶體使用情況。對於特定容器的記憶體指標請設定具有增強可觀測性的 CloudWatch Container Insights

若要分析一段時間內容器的記憶體使用情況,請在 CloudWatch Logs Insights 中使用自訂查詢。

查詢範例:

stats max(MemoryUtilized) as mem, max(MemoryReserved ) as memreserved by bin (5m) as period, TaskId, ContainerName
| sort period desc
| filter ContainerName like "example-container-name"
| filter TaskId = "example-task-id"

**注意:**將 example-container-name 替換為您的容器名稱,將 example-task-id 替換為您的任務 ID。

在 Amazon ECS 任務和容器中設定記憶體配額

在任務層級,您可以為整個任務設定硬性記憶體配額。在容器層級,您可以使用 memoryReservation (記憶體軟性限制) 和 memory (記憶體硬性限制) 參數來分配記憶體。

在部署應用程式之前,請確認您的主機有足夠的可用記憶體。然後,使用軟性、硬性記憶體配額更新您的任務定義

**注意:**您只能在 Linux 容器中使用 memoryReservation 參數。

任務定義範例:

"containerDefinitions": [
    {
        "name": "example-container-name",
        "memory": 1024,
        "memoryReservation": 512
        // ... other container properties
    }
]

為具有高瞬時記憶體需求的容器設定 swap 分區

**注意:**若要使用 maxSwapsharedMemorySize 參數,您的任務必須使用 Amazon Elastic Compute Cloud (Amazon EC2) 啟動類型。

如果您的容器經歷高頻率的暫時性記憶體使用高峰,請更新任務定義以使用 swap 分區組態。swap 分區可減少高負載期間發生的 OutofMemory 錯誤。然而,swap 分區也會降低您的應用程式效能。啟用 swap 分區後,監控應用程式的效能。

根據執行時期框架調整應用程式的記憶體設定

當達到框架或執行時期預設記憶體配額時,即使系統有可用的記憶體或增加了容器配額,應用程式也可能會停止執行。若要解決此問題,請監視應用程式的記憶體使用模式。確定您的框架或執行時期的預設記憶體設定,然後調整任務記憶體參數,以符合您應用程式的要求。

Java 應用程式

Java 虛擬機器 (JVM) 在啟動時需要作業系統 (OS) 分配初始記憶體,並且具有最大記憶體使用配額。如需詳細資訊,請參閱 Oracle 網站上的 java.lang.OutOfMemoryError 錯誤。若要調整記憶體值,請使用 JVM 標幟。例如,執行以下命令以使用 -Xms 設定初始堆積大小,並使用 -Xmx 設定最大堆積大小:

java -Xms512m -Xmx2048m -jar your-app.jar

若要啟動詳細的垃圾回收 (GC) 記錄,請將下列 JVM 引數新增至 Java 命令:

-verbose:gc -Xlog:gc*:file=log_filename:time,uptime:filecount=num_files,filesize=file_sizem

如需詳細資訊,請參閱 Oracle 網站上的垃圾回收日誌

對於進階記憶體診斷,請使用 jcmdjmap 產生堆積傾印和分析工具,如 JDK Mission Control 或 VisualVM。如需詳細資訊,請參閱 Oracle 網站上的診斷資料分析工具

Node.js 應用程式

使用以下 v8.getHeapStatistics() 模組來檢查預設堆積記憶體配額:

const v8 = require('v8');
console.log(v8.getHeapStatistics());

如需詳細資訊,請參閱 Node.js 網站上的 v8.getHeapStatistics()

若要增加堆積大小配額,請在執行應用程式時,使用 --max-old-space-size 參數:

node --max-old-space-size=4096 app.js

**注意:**上述命令設定了 4 千兆位元組 (GB) 的堆積配額。預設堆積記憶體大小在不同的 Node.js 版本中可能有所不同。如需詳細資訊,請參閱 Node.js 網站上的 --max-old-space-size=SIZE (以 MiB 為單位)

若要追蹤垃圾回收,請在節點程序中新增以下標幟:

node --trace-gc server.js

如需詳細資訊,請參閱 Node.js 網站上的追蹤垃圾回收

若要進行深入的記憶體診斷,請使用 Node.js V8 內建分析工具 (例如 --heap-prof) 來建立堆積快照。或者,使用 --heapsnapshot-signal 以使用 Linux 訊號來建立堆積快照。如需詳細資訊,請參閱 Node.js 網站上的 --heap-prof使用堆積快照

擴展您的服務,以最佳化服務層級記憶體使用情況

若要最佳化服務層級記憶體使用情況,請監控並調整資源分配,以根據記憶體使用模式擴展任務。計算服務任務所使用的總記憶體。然後,根據您的記憶體需求,手動調整服務中所需的任務值

或者,使用以記憶體使用量指標為基礎服務擴展政策。設定具有閾值的擴展政策來橫向擴充和縮減。

避免將來出現 OutofMemory 錯誤

若要避免將來出現 OutofMemory 錯誤,請對主機或伺服器內的容器執行負載測試,以確定應用程式的記憶體需求。測試時,使用 Docker 容器統計資料來監控容器的記憶體使用情況。如需詳細資訊,請參閱 Docker 網站上的 Docker 容器統計資料

若要更新容器組態,請執行下列動作:

  • 管理資料結構。
  • 避免建立不必要的物件。
  • 實作快取。
  • 使用高效率的演算法來減少記憶體佔用量。

相關資訊

如何對在容器結束時停止或無法啟動的 Amazon ECS 任務進行疑難排解?

AWS 官方
AWS 官方已更新 1 個月前