好久沒更新了姆坚,。膏蚓。瓢谢。太懶了。
在跑Spark-On-Yarn程序的時候驮瞧,往往會對幾個參數(shù)(num-executors氓扛,executor-cores,executor-memory等)理解很模糊剧董,從而憑感覺地去指定值幢尚,這是不符合有追求程序員信仰的破停。因此翅楼,搞懂它們尉剩,很有必要。
本文翻譯自https://spoddutur.github.io/spark-notes/distribution_of_executors_cores_and_memory_for_spark_application.html毅臊。
譯文如下:
是否曾經(jīng)想要知道如何根據(jù)你的集群理茎,配置這些Spark運行參數(shù):--num-executors, --executor-memory and --execuor-cores 呢?
探究思路
- 理論引導:首先管嬉,有必要了解一些重要建議皂林,能幫助我們更好地理解它;
- 實戰(zhàn):其次蚯撩,以一個集群為例础倍,推演出該集群的參數(shù)的推薦值。
理論引導
當配置參數(shù)時胎挎,請遵循下表沟启,將其推薦建議牢記于心
- Hadoop/Yarn/OS 守護進程:
當利用一個集群管理器(比如YARN)運行spark程序時,存在一些守護進程運行在后臺犹菇,比如NameNode德迹,Secondary NameNode,DataNode揭芍,JobTracker和TaskTracker胳搞。因此,當確定num-executor時称杨,我們需要確保有足夠的cores(大約每個節(jié)點一個core)維持這些守護進程的平穩(wěn)運行肌毅。 - Yarn ApplicationMaster (AM):
ApplicationMaster的職責是:向ResourceManager協(xié)商資源,與NodeManager一同執(zhí)行并監(jiān)控containner及其資源消耗姑原。如果程序運行在Spark-On-Yarn悬而,我們需要預留一些資源給ApplicationMaster,AM大約需要1024MB的內(nèi)存和一個Executor页衙。 - HDFS吞吐:
HDFS客戶端會遇到大量并發(fā)線程的問題摊滔。 據(jù)觀察,HDFS當達到全寫入吞吐量時店乐,需要每個executor執(zhí)行約5個任務艰躺。 因此,最好控制每個executor中core的數(shù)目低于那個數(shù)字眨八。 - 內(nèi)存開銷:
下圖描繪了spark-yarn的內(nèi)存使用情況:
[圖片上傳失敗...(image-fa6806-1536392056623)]
圖中注意兩件事情:
Full memory requested to yarn per executor =
spark-executor-memory + spark.yarn.executor.memoryOverhead
spark.yarn.executor.memoryOverhead =
Max(384MB, 7% of spark.executor-memory)
所以腺兴,如果我們申請了每個executor的內(nèi)存為20G時,對我們而言廉侧,AM將實際得到20G+ memoryOverhead = 20 + 7% * 20GB = ~23G內(nèi)存页响。
- 執(zhí)行擁有太多內(nèi)存的executor會產(chǎn)生過多的垃圾回收延遲
- 執(zhí)行過小的executor(舉例而言篓足,一個只有一核和僅僅足夠內(nèi)存跑一個task的executor),將會丟失在單個JVM中運行多任務的好處闰蚕。
理論夠了...開始實戰(zhàn)
現(xiàn)在栈拖,我們考慮一個10個節(jié)點的如下配置的集群,并分析不同參數(shù)設置的結果没陡。
集群配置如下:
**集群配置:**
10個節(jié)點
每個節(jié)點16核
每個節(jié)點64G內(nèi)存
第一種方案:Tiny executors [每個Executor一個Core]
Tiny executors表示一個executor配置一個core涩哟。下表描述了該方案下的參數(shù)配置。
- '--num-executors' = '該方案下盼玄,每個executor配置一個core'
= '集群中的core的總數(shù)'
= '每個節(jié)點的core數(shù)目 * 集群中的節(jié)點數(shù)'
= 16 x 10 = 160
- '--executor-cores' = 1 (每個executor一個core)
- '--executor-memory' = '每個executor的內(nèi)存'
= '每個節(jié)點的內(nèi)存/每個節(jié)點的executor數(shù)目'
= 64GB/16 = 4GB
分析:當一個executor只有一個core時贴彼,正如我們上面分析的,我們可能不能發(fā)揮在單個JVM上運行多任務的優(yōu)勢埃儿。此外器仗,共享/緩存變量(如廣播變量和累加器)將復制到節(jié)點的每個core,這里是16次童番。并且精钮,我們沒有為Hadoop / Yarn守護進程留下足夠的內(nèi)存開銷,我們也沒有計入ApplicationManager妓盲。因此杂拨,這不是一個好的方案!
第二種方案:Fat executors (每個節(jié)點一個Executor):
Fat executors表示一個executor獨占一個節(jié)點悯衬。下表描述了該方案下的參數(shù)配置:
- `--num-executors` = `該方案下弹沽,一個executor獨占一個節(jié)點`
= `集群中的節(jié)點的數(shù)目`
= 10
- `--executor-cores` = `一個節(jié)點一個executor意味著每個executor獨占節(jié)點中所
有的cores`
= `節(jié)點中的core的數(shù)目`
= 16
- `--executor-memory` = `每個executor的內(nèi)存`
= `節(jié)點的內(nèi)存/節(jié)點中executor的數(shù)目`
= 64GB/1 = 64GB
分析:每個executor獨占16個核心,則ApplicationManager和守護程序進程則無法分配到core筋粗,并且策橘,HDFS吞吐量會受到影響,導致過多的垃圾結果娜亿。 同樣地丽已,該方案不好!
第三種方案:Balance between Fat (vs) Tiny
根據(jù)上面討論的建議:
- 基于上述的建議买决,我們給每個executor分配5個core => -- executor-cores = 5 (保證良好的HDFS吞吐)
- 每個節(jié)點留一個core給Hadoop/Yarn守護進程 => 每個節(jié)點可用的core的數(shù)目 = 16 - 1
- 所以沛婴,集群中總共可用的core的數(shù)目是 15 * 10 = 150
- 可用的executor的數(shù)目 = (總的可用的core的數(shù)目 / 每個executor的core的數(shù)目)= 150 / 5 = 30
- 留一個executor給ApplicationManager => --num-executors = 29
- 每個節(jié)點的executor的數(shù)目 = 30 / 10 = 3
- 每個executor的內(nèi)存 = 64GB / 3 = 21GB
- 計算堆開銷 = 7% * 21GB = 3GB。因此督赤,實際的 --executor-memory = 21 - 3 = 18GB
因此嘁灯,推薦的配置如下:29 executors, 18GB memory each and 5 cores
each !
分析:很明顯躲舌,第三種方案在Fat vs Tiny 兩種方案中找到了合適的平衡點丑婿。毋庸置疑,它實現(xiàn)了Fat executor的并行性和Tiny executor的最佳吞吐量!
結論:
我們看到:
- 當為spark程序配置運行參數(shù)的時候羹奉,應謹記一些推薦事項:
1.為Yarn的Application Manager預留資源
2.我們應該如何為Hadoop / Yarn / OS deamon進程節(jié)省一些cores
3.學習關于spark-yarn-memory-usage - 另外秒旋,檢查并分析了配置這些參數(shù)的三種不同方法:
1.Tiny Executors - 每個executor配置一個core
2.Fat Executors - 每個executor獨占一個節(jié)點
3.推薦方案 - 基于建議項的Tiny(Vs)Fat的合適的平衡。
--num-executors, --executor-cores and --executor-memory..這三個參數(shù)在spark性能中扮演很重要的角色诀拭,他們控制這你的spark程序獲得的CPU和內(nèi)存的資源迁筛。對于用戶來說,很有必要理解如何去配置它們炫加。希望這篇博客對你有幫助瑰煎。