一篇文章搞清spark任務如何執行

本文將針對spark中的Driver和Executor講起,簡述了spark的運行流程,部署模式以及內部任務調度機制,希望針對spark任務執行過程進行儘可能好理解的解析

1.兩個重要的主角

​ 在spark中,有兩個重要的主角是繞不開的,driver和executor,他們的結構呈一主多從模式,driver就是那個單身狗,控制慾很強,權利也很大,每天獨自一人沒別的事,就想法設法的指揮着手下一堆executor到處幹活。他們分工明確,組織結構簡單,共同支撐起了spark強大的計算引擎。

Driver

​ Spark 驅動器節點,用於執行 Spark 任務中的 main 方法,負責實際代碼的執行工作。Driver 在 Spark 作業執行時主要負責:

1. 將代碼邏輯轉化爲任務;

2. 在 Executor 之間調度任務(job);

3. 跟蹤 Executor 的執行情況(task)。

Executor

​ Spark 執行器節點,負責在 Spark 作業中運行具體任務,任務之間相互獨立。Spark 應用啓動時,Executor 節點被同時啓動,並且始終伴隨着整個 Spark 應用的生命週期而存在。如果有 Executor 點發生了故障或崩潰,Spark 應用也可以繼續執行,會將出錯節點上的任務調度到其他 Executor 節點上繼續運行。Executor 有兩個核心功能:

1. 負責運行組成 Spark 應用的任務,並將結果返回給驅動器進程;

2. 通過自身的塊管理器(Block Manager)爲用戶程序中要求緩存的 RDD提供內存式存儲。RDD 是直接緩存在 Executor 進程內的,因此任務可以在運行時充分利用緩存數據加速運算。

Spark 運行流程

​ 不論spark以何種方式部署,在任務提交後,都先啓動Driver,然後Driver向集羣管理器註冊應用程序,之後集羣管理器根據此任務的配置文件分配Executor並啓動,然後Driver等待資源滿足,執行 main 函數,Spark的查詢爲懶執行,當執行到 action 算子時纔開始真正執行,開始反向推算,根據寬依賴進行 stage 的劃分,隨後每一個 stage 對應一個 taskset,一個taskset 中有多個 task,task 會被分發到指定的 Executor 去執行,在任務執行的過程中,Executor 也會不斷與 Driver 進行通信,報告任務運行情況。

2.spark的部署模式

2.1 spark部署類型

Spark共支持3種集羣管理器,Standalone,Mesos和Yarn

  • Standalone:

獨立模式,Spark 原生的最簡單的一個集羣管理器。 它可以運行在各種操作系統上,自帶完整的服務,無需依賴任何其他資源管理系統,使用 Standalone 可以很方便地搭建一個集羣。

  • Apache Mesos

    Mesos也是一個強大的分佈式資源管理框架,是以與Linux內核同樣的原則而創建的,允許多種不同的框架部署在其上

  • Hadoop Yarn

    Hadoop生態下的統一資源管理機制,在上面可以運行多套計算框架,如mapreduce、spark 等,根據 driver 在集羣中的位置不同,部署模式可以分爲 yarn-client 和 yarn-cluster。

    Spark 的運行模式取決於傳遞給 SparkContext 的 MASTER 環境變量的值,spark在yarn上部署:

    1. yarn-client:Driver在本地,Executor在Yarn集羣,配置:--deploy-mode client
    2. yarn-cluster:Driver和Executor都在Yarn集羣,配置:--deploy-mode cluster

2.2 Yarn模式下的運行機制

當前流行的工作模式均是將spark提交到Yarn上,所以這裏我們針對spark on Yarn做一下詳細瞭解。

  • yarn-client 模式

​ 在YARNClient模式下,Driver在任務提交的本地機器上運行,Driver會向ResourceManager申請啓動ApplicationMaster,隨後ResourceManager分配container,在合適的NodeManager上啓動ApplicationMaster,此時的ApplicationMaster的功能相當於一個ExecutorLaucher,只負責向ResourceManager申請Executor內存。
  ResourceManager接到ApplicationMaster的資源申請後會分配container,然後
ApplicationMaster在資源分配指定的NodeManager上啓動Executor進程,Executor進程啓動後會向Driver反向註冊。另外一條線,Driver自身資源滿足的情況下,Driver開始執行main函數,之後執行Action算子時,觸發一個job,並根據寬依賴開始劃分stage,每個stage生成對應的taskSet,Executor註冊完成後,Driver將task分發到各個Executor上執行。

  • yarn-cluster

​ 在 YARN Cluster 模式下,任務提交後會和 ResourceManager 通訊申請啓動ApplicationMaster,隨後 ResourceManager 分配 container,在合適的 NodeManager上啓動 ApplicationMaster,此時的ApplicationMaster 就是 Driver。

​ Driver 啓動後向 ResourceManager 申請 Executor 內存,ResourceManager會分配container,然後在合適的 NodeManager 上啓動 Executor 進程,Executor 進程啓動後會向 Driver 反向註冊。另外一條線,Driver自身資源滿足的情況下,開始執行main函數,之後執行Action算子時,觸發一個job,並根據寬依賴開始劃分stage,每個stage生成對應的taskSet,Executor註冊完成後,Driver將task分發到各個Executor上執行。

3.Spark 任務調度

​ Driver會根據用戶程序準備任務,並向Executor分發任務,在這兒有幾個Spark的概念需要先介紹一下:

  • Job:以Action算子爲界,遇到一個Action方法就觸發一個Job

  • Stage:Job的子集,一個job至少有一個stage,以shuffle(即RDD寬依賴)爲界,一個shuffle劃分一個stage

  • Task: Stage 的子集,以並行度(分區數)來衡量,分區數是多少,則有多少

    個 task。

spark在具體任務的調度中,總的分兩路進行:Stage級別調度和Task級別調度。Spark RDD通過轉換(Transactions)算子,形成了血緣關係圖DAG,最後通過行動(Action)算子,觸發Job並調度執行。

DAGScheduler負責Stage級的調度,主要是將DAG切分成若干Stages,並將每個Stage打包成TaskSet交給TaskScheduler調度。

TaskScheduler負責Task級的調度,將DAGScheduler給過來的TaskSet按照指定的調度策略分發到Executor上執行

3.1 Spark Stage級調度

​ Spark的任務調度是從DAG切割開始,主要是由DAGScheduler來完成。當遇到一個Action操作後就會觸發一個Job的計算,並交給DAGScheduler來處理。

DAGScheduler主要做兩個部分的事情:

  1. 切分stage

​ DAGScheduler會根據RDD的血緣關係構成的DAG進行切分,將一個Job劃分爲若干Stages,具體劃分策略是:從後往前,由最終的RDD不斷通過依賴回溯判斷父依賴是否是寬依賴,遇到一個shuffle就劃分一個Stage。無shuffle的稱爲窄依賴,窄依賴之間的RDD被劃分到同一個Stage中。劃分的Stages分兩類,一類叫做ResultStage,爲DAG最下游的Stage,由Action方法決定,另一類叫做ShuffleMapStage,爲下游Stage準備數據。

​ stage任務調度本身是一個反向的深度遍歷算法,以下圖wordcount爲例。此處只有saveAsTextFile爲行動算子,該 Job 由 RDD-3 和 saveAsTextFile方法組成,根據依賴關係回溯,知道回溯至沒有依賴的RDD-0。回溯過程中,RDD-2和RDD-3存在reduceByKey的shuffle,會劃分stage,由於RDD-3在最後一個stage,即劃爲ResultStage,RDD-2,RDD-1,RDD-0,這些依賴之間的轉換算子flatMap,map沒有shuffle,因爲他們之間是窄依賴,劃分爲ShuffleMapStage。

  1. 打包Taskset提交Stage

​ 一個Stage如果沒有父Stage,那麼從該Stage開始提交,父Stage執行完畢才能提交子Stage。Stage提交時會將Task信息(分區信息以及方法等)序列化並被打包成TaskSet交給TaskScheduler,一個Partition對應一個Task,另一方面TaskScheduler會監控Stage的運行狀態,只有Executor丟失或者Task由於Fetch失敗才需要重新提交失敗的Stage以調度運行失敗的任務,其他類型的Task失敗會在TaskScheduler的調度過程中重試。

3.2 Spark Task 級調度

​ SparkTask的調度是由TaskScheduler來完成,TaskScheduler將接收的TaskSet封裝爲TaskSetManager加入到調度隊列中。同一時間可能存在多個TaskSetManager,一個TaskSetManager對應一個TaskSet,而一個TaskSet含有n多個task信息,這些task都是同一個stage的。

​ TaskScheduler初始化後會啓動SchedulerBackend,它負責跟外界打交道,接收Executor的註冊信息,並維護Executor的狀態,SchedulerBackend會監控到有資源後,會詢問TaskScheduler有沒有任務要運行,TaskScheduler會從調度隊列中按照指定的調度策略選擇TaskSetManager去調度運行。

​ TaskSetManager按照一定的調度規則一個個取出task給TaskScheduler,TaskScheduler再交給SchedulerBackend去發到Executor上執行。

​ Task被提交到Executor啓動執行後,Executor會將執行狀態上報給SchedulerBackend,SchedulerBackend則告訴TaskScheduler,TaskScheduler找到該Task對應的TaskSetManager,並通知到該TaskSetManager,這樣TaskSetManager就知道Task的運行狀態

3.3 失敗重試和白名單

​ 對於運行失敗的Task,TaskSetManager會記錄它失敗的次數,如果失敗次數還沒有超過最大重試次數,那麼就把它放回待調度的Task池子中等待重新執行,當重試次數過允許的最大次數,整個Application失敗。在記錄Task失敗次數過程中,TaskSetManager還會記錄它上一次失敗所在的ExecutorId和Host,這樣下次再調度這個Task時,會使用黑名單機制,避免它被調度到上一次失敗的節點上,起到一定的容錯作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章