Spark on Yarn 執行單元數、內存、CPU 數的推薦分配

本文翻譯自: Managing Relations Inside Elasticsearch | Elastic

是否曾經有過疑問:--num-executors, --executor-memory and --execuor-cores 這些參數該如何配置?緩存

  1. 讓咱們看一些建議以便可以更好的理解
  2. 親自動手,用一些示例集羣來推到合適的參數

理論先行

如下是一些配置時的建議內容:服務器

  • Hadoop/Yarn/OS 守護進程:當咱們在 Yarn 一類的集羣管理器中運行 Spark 應用時,後臺會伴隨着守護進程的運行,好比:NameNode,Secondary NameNode,DataNode,JobTracker,以及 TaskTracker。於是,當指定 num-executors 時,咱們須要保證留有足夠的 CPU 核樹(每一個節點 1 核)以確保這些守護進程可以順利運行。
  • Yarn ApplicationMaster (AM):ApplicationMaster 會從 ResourceManager 那裏申請資源,並經過 NodeManager 執行並監控 Container 及其中的資源消耗。若是在 Yarn 中啓動應用,咱們須要爲 AM 流出所需的資源( 大約 1024MB 的內存以及 1 個 Executor )
  • HDFS 吞吐:HDFS 客戶端應對大量的併發線程性能不佳。據觀察,當達到每一個執行單元 5 個任務時,HDFS 會達到上限的吞吐量。於是,最好保證每一個 Executor 的核數低於這個值。
  • 內存開銷:下圖描述了 Spark on Yarn 的內存佔用狀況:

從上圖中,咱們須要注意兩件事:併發

  1. 每一個 Executor 所申請的內存 = spark-executor-memory + spark.yarn.executor.memoryOverhead
  2. spark.yarn.executor.memoryOverhead = Max( 384MB, 7% * spark.executor-memory )

也就是說,若是咱們爲每一個 Executor 申請 20GB內存,AM 實際上將會申請 20GB + memoryOverhead = 20 + 20 * 7% ~= 23GB。elasticsearch

  • Executor 中含有過多內存一般會致使過分的 GC 延遲;
  • Thiy Executor( 僅含有單核,以及僅僅足夠單個 task 運行所需的內存 )會失去在單個 JVM 中運行多個任務的優點。

動手實踐

如今,假設咱們有 10 個服務器節點,他們的配置以下:ide

**服務器配置**

節點數:10
單個節點核數:16
單個節點內存:64GB

讓咱們考慮一下不一樣的參數配置:oop

方法一:Tiny Executor( 每一個 Executor 單核 )

Tiny Executor 意味着每一個 Executor 僅有一個核。下表在這一狀況下的參數配置:性能

- --num-executors = 節點總核數
                    = 單個節點核數 * 集羣的節點個數 
                    = 16 x 10 = 160
- --executor-cores = 1 ( 每一個 executor 單核 )
- --executor-memory = 每一個 Executor 的內存數
                     = 每一個節點的內存數 / 每一個節點的 Executor 數
                     = 64GB / 16 = 4GB

分析: 如上述,當每一個 Executor 僅有一個核時,咱們沒法利用同一 JVM 運行多個 task 的優點。一樣的,利用 broadcastaccumulator 進行變量共享/緩存時,須要在每一個節點的每一個核中進行復制操做。此外,咱們也沒有爲 Hadoop/Yarn 守護進程留有足夠的內存資源。這種方法很差。spa

方法二:Fat Executor( 每一個節點一個 Executor )

Fat Executor 意味着每一個節點一個 Executor,下表展現了相應的 Spark 配置:線程

- --num-executors = 集羣節點數
                  = 10
- --executor-cores = 單節點核數
                    = 16
- --executor-memory = 單節點內存數 / 每一個節點的 Executor 數
                     = 64GB / 1 = 64GB

分析: 當每一個 Executor 分配 16 核時,除了 AM 和守護進程沒有考慮在內之外,HDFS 的吞吐將會受制,且將會致使國度的 GC。由於,這種方法很差。翻譯

方法三:Fat 和 Tiny 之間的平衡方案

根據咱們以前的建議:

  • 基於上述建議,讓咱們爲每一個 Executor 分配 5 核 => --executor-cores = 5 ( 爲了更好地 HDFS 吞吐 )
  • 在每一個節點中,爲 Hadoop/Yarn 守護進程留出 1 核 => 單節點的可用核數 = 16 - 1 = 15
  • 於是,總可用核數 = 15 * 10 = 150
  • 可用的 executor 數 = ( 總核數 / 每一個 executor 的核數 )= 150 / 5 30
  • 留出一個 Executor 用於 ApplicationMaster => --num-executors = 29
  • 每一個節點的 Executor 數 = 30 / 10 = 3
  • 每一個節點的內存數 = 64GB / 3 ~= 21 GB
  • 計算額外開銷 = 7% * 21 GB = 3 GB。於是,實際的 --executor-memory = 21 - 3 = 18 GB

於是,推薦的配置爲:29 個 Executor,每一個 Executor:18 GB 內存及 5 核。

分析:不難看出方法三是如何在 Fat 和 Tiny 之間保持平衡的。其保證了 Fat Executor 的並行度及 Tiny Executor 的吞吐量。

結論

以下:

在對 Spark 應用的配置時記住以下建議:

  • 爲 Yarn AM 預留所需的資源;
  • 爲 Hadoop/Yarn/OS 守護進程預留資源;
  • 瞭解 Spark 內存利用模型

此外,分析三種參數配置方法:

  1. Tiny Executors - 單核 Executor
  2. Fat Executor - 每一個節點對應一個 Executor
  3. 推薦的作法 - 按上述建議在 Fat 和 Tiny 之間保持平衡

--num-executors--executor-cores and --executor-memory 這三個參數控制了 Spark 應用所能使用的 CPU 數量及內存數,在 Spark 性能上起到相當重要的做用。讓用戶理解配置的正確方法是相當重要的。但願這篇博客可以幫助你瞭解這些。

相關文章
相關標籤/搜索