我想要疑難排解 Amazon EMR 上 Spark 中的「Container killed by YARN for exceeding memory limits」錯誤。
解決方法
此錯誤的根本原因和適當的解決方案取決於您的工作負載。若要對此錯誤進行疑難排解,請依照以下順序使用以下疑難排解方法。
增加記憶體額外負荷
記憶體額外負荷是指配置給每個執行程式的堆積外記憶體量。根據預設,Spark 會將記憶體額外負荷設為執行程式記憶體的 10% 或 384,以較高者為準。Java NIO 直接緩衝區、執行緒堆疊、共用原生程式庫和記憶體對應檔案都會使用此記憶體額外負荷。
逐步增加記憶體額外負荷,最多增加到 25%。驅動程式或執行程式記憶體與記憶體額外負荷的總和必須小於您執行個體類型的 yarn.nodemanager.resource.memory-mb:
「spark.driver/executor.memory + spark.driver/executor.memoryOverhead < yarn.nodemanager.resource.memory-mb」
如果錯誤發生在驅動程式容器或執行程式容器,請只增加發生錯誤之容器的記憶體額外負荷。您可以在執行中的叢集、新叢集上增加記憶體額外負荷,或在提交作業時增加。
執行中的叢集
在主要節點上修改 spark-defaults.conf。
例如:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.driver.memoryOverhead 512
spark.executor.memoryOverhead 512
新叢集
在啟動叢集時,新增與以下範例類似的組態物件:
[
{
"Classification": "spark-defaults",
"Properties": {
"spark.driver.memoryOverhead": "512",
"spark.executor.memoryOverhead": "512"
}
}
]
單一作業
若要在執行 spark-submit 時增加記憶體額外負荷,請使用 --conf 選項。
範例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --conf spark.driver.memoryOverhead=512 --conf spark.executor.memoryOverhead=512 /usr/lib/spark/examples/jars/spark-examples.jar 100
如果您在增加記憶體額外負荷後仍持續收到此錯誤,請減少執行程式核心數。
減少執行程式核心數
**注意:**還原您在前一節中對 spark-defaults.conf 所做的任何變更。
當您減少執行程式核心數時,會減少執行程式可執行的最大任務數,進而減少所需的記憶體量。根據擲回錯誤的驅動程式容器或發生錯誤的其他執行程式容器,減少驅動程式或執行程式的核心數。
執行中的叢集
在主要節點上修改 spark-defaults.conf。
範例:
sudo vim /etc/spark/conf/spark-defaults.confspark.driver.cores 3
spark.executor.cores 3
新叢集
在啟動叢集時,新增與以下範例類似的組態物件:
[
{
"Classification": "spark-defaults",
"Properties": {"spark.driver.cores" : "3",
"spark.executor.cores": "3"
}
}
]
單一作業
若要在執行 spark-submit 時減少執行程式核心數,請使用 —executor-cores 選項。
範例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --executor-cores 3 --driver-cores 3 /usr/lib/spark/examples/jars/spark-examples.jar 100
如果您仍持續收到錯誤訊息,請增加分區數。
增加分區數
**注意:**還原您在前一節中對 spark-defaults.conf 所做的任何變更。
若要增加分區數,請增加原始彈性分散式資料集的 spark.default.parallelism 值,或執行 .repartition() 作業。
當您增加分區數時,會減少每個分區所需的記憶體量。Spark 會大量使用叢集 RAM,作為最大化速度的有效方式。因此,您必須使用 Amazon EMR 6.15 的 Ganglia 或 Amazon EMR 7.0 及更新版本的 Amazon CloudWatch 代理程式來監控記憶體使用量。然後確認您的叢集設定和分區策略符合持續成長的資料需求。如果您仍持續收到「Container killed by YARN for exceeding memory limits」錯誤訊息,請增加驅動程式和執行程式記憶體。
增加驅動程式和執行程式記憶體
**注意:**還原您在前一節中對 spark-defaults.conf 所做的任何變更。
如果錯誤發生在驅動程式容器或執行程式容器,請只增加驅動程式或執行程式其中一者的記憶體,不要同時增加兩者的記憶體。請確保驅動程式或執行程式記憶體加上驅動程式或執行程式記憶體額外負荷的總和,始終小於您 EC2 執行個體類型的 yarn.nodemanager.resource.memory-mb 值:
「spark.driver/executor.memory + spark.driver/executor.memoryOverhead < yarn.nodemanager.resource.memory-mb」
執行中的叢集
在主要節點上修改 spark-defaults.conf。
範例:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.executor.memory 1g
spark.driver.memory 1g
新叢集
在啟動叢集時,新增與以下內容類似的組態物件:
[
{
"Classification": "spark-defaults",
"Properties": {
"spark.executor.memory": "1g",
"spark.driver.memory":"1g",
}
}
]
單一作業
在執行 spark-submit 時,使用 --executor-memory 和 --driver-memory 選項來增加記憶體。
範例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --executor-memory 1g --driver-memory 1g /usr/lib/spark/examples/jars/spark-examples.jar 100
其他疑難排解步驟:
如果您仍持續收到錯誤訊息,請採取以下動作:
- 針對範例資料集執行您的應用程式。最佳實務是基準測試,可協助您發現會導致記憶體問題的效能降低和偏斜分區。
- 處理所需的最少資料量。如果您未篩選資料,或是在應用程式執行的較後階段才篩選資料,多餘資料可能會使應用程式變慢。這可能會增加發生記憶體例外狀況的機率。
- 分區您的資料,以便只擷取所需的資料。
- 使用不同的分區策略。例如,依替代索引鍵進行分區,以避免大型分區和偏斜分區。
- 您的 EC2 執行個體可能沒有足夠的記憶體資源來支援您的工作負載。切換到較大的記憶體最佳化執行個體類型。如果您在變更執行個體類型後仍持續發生記憶體例外狀況,請在新執行個體上嘗試這些疑難排解方法。
相關資訊
Apache Spark 網站上的 Spark 組態
如何解決 Amazon EMR 上 Spark 中的「java.lang.ClassNotFoundException」錯誤?