轉載於:https://www.cnblogs.com/lestatzhang/p/10611321.html
前言
在我們提交spark程序時,應該如何為Spark集群配置–num-executors, - executor-memory和–execuor-cores 呢?
一些資源參數設置的基本知識
- Hadoop / Yarn / OS Deamons
當我們使用像Yarn這樣的集群管理器運行spark應用程序時,會有幾個守護進程在后台運行,如NameNode,Secondary NameNode,DataNode,JobTracker和TaskTracker等。因此,在指定num-executors時,我們需要確保為這些守護進程留下足夠的核心(至少每個節點約1 CPU核)以便順利運行。 - Yarn ApplicationMaster(AM)
ApplicationMaster負責協調來自ResourceManager的資源,並與NodeManagers一起執行container並監控其資源消耗。如果我們在YARN上運行Spark,那么我們需要預估運行AM所需要的資源(至少1024MB和1 CPU核)。 - HDFS吞吐量
HDFS客戶端遇到大量並發線程會出現一些bug。一般來說,每個executors最多可以實現5個任務的完全寫入吞吐量,因此最好將每個executors的核心數保持在該數量之下。 - MemoryOverhead
JVM還需要一些off heap的內存,請參考下圖中描繪的Spark和YARN中內存屬性的層次結構,
簡單來說,有以下兩個公式:
例如當我設置 --executor-memory=20時, 我們實際請求了
運行具有executors大內存的通常會導致過多的GC延遲。
運行較小的executors(例如,1G & 1 CPU core)則會浪費 單個JVM中運行多個任務所帶來的優點。
不同配置的優劣分析
現在,假設我們的集群配置如下
10 Nodes
16 cores per Node
64GB RAM per Node
第一種方法:使用較小的executors
`--num-executors` = `在這種方法中,我們將為每個核心分配一個executor`
= `集群的總核心數`
= `每個節點的核心數 * 集群的總節點數`
= 16 x 10 = 160
`--executor-cores` = 1 (`每個executor分配的核心數目`)
`--executor-memory` = `每個executor分配的內存數`
= `每個節點內存總數數/每個節點上分配的executor數`
= 64GB/16 = 4GB
分析:
由於每個executor只分配了一個核,我們將無法利用在同一個JVM中運行多個任務的優點。 此外,共享/緩存變量(如廣播變量和累加器)將在節點的每個核心中復制16次。 最嚴重的就是,我們沒有為Hadoop / Yarn守護程序進程留下足夠的內存開銷,我們還忘記了將ApplicationManagers運行所需要的開銷加入計算。
第二種方法:使用較大的executors
`--num-executors` = `在這種方法中,我們將為每個節點分配一個executor`
= `集群的總節點數`
= 10
`--executor-cores` = `每個節點一個executor意味着該節點的所有核心都分配給一個執executor`
= `每個節點的總核心數`
= 16
`--executor-memory` = `每個executor分配的內存數`
= `每個節點內存總數數/每個節點上分配的executor數`
= 64GB/1 = 64GB
分析:
每個executor都有16個核心,由於HDFS客戶端遇到大量並發線程會出現一些bug,即HDFS吞吐量會受到影響。同時過大的內存分配也會導致過多的GC延遲。
第三種方法:使用優化的executors
- 基於上面提到的建議,讓我們為每個執行器分配5個核心, 即
--executor-cores = 5
- 為每個節點留出1個核心用於Hadoop / Yarn守護進程, 即每個節點可用的核心數 = 16-1 = 15。 因此,群集中核心的可用總數= 15 x 10 = 150
- –num-executors =(群集中核心的可用總數/每個executors分配的核心數)= 150/5 = 30
- 為ApplicationManager留下預留1個executors的資源, 即
--num-executors = 29
- 每個節點的executors數目 = 30/10 = 3
- 群集中每個節點的可使用的總內存數 64GB - 1GB = 63GB
- 每個executor的內存= 64GB / 3 = 21GB
- 預留的 off heap overhead = 21GB * 7% ~ 1.47G
- 所以,實際的
--executor-memory = 21 - 1.47G ~ 19GB
參考資料
how-to-tune-your-apache-spark-jobs-part-2
distribution_of_executors_cores_and_memory_for_spark_application