DAGScheduler:根據寬依賴操作,劃分stage,將stage中的task封裝成tastset
TaskScheduler:接收DAGScheduler提交的調度階段,並將任務發送到節點,在節點執行任務。
1)針對RDD做各種轉換操作,行動操作會觸發job的生成,根據RDD血緣關係構建DAG圖,DAGScheduler負責解析DAG圖、
2)DAGScheduler根據寬依賴將DAG拆分成相互依賴的各個stage,每個stage包含若干個task,每個stage的task形成任務集,提交給TaskScheduler調度。
DAGScheduler計算最優的調度策略,例如選擇數據本地化策略。
DAGScheduler監控調度過程,如果某個stage失敗,DAGScheduler負責重新提交這一stage。
3)每個TaskScheduler只爲一個SparkContext服務。TaskScheduler接收來自DAGScheduler分發的任務集,並分發給各個Executor執行。TaskScheduler負責監控任務執行情況,負責任務重試機制。
4)Executor接收TaskScheduler的任務集,一個任務交給一個線程執行,任務執行完成要將任務信息返回給TaskScheduler。
ShuffleMapTask返回MapStatus對象,而不是結果本身;ResultTask返回的結果參照如下所述。
獲取執行結果
對於Executor返回的計算結果:
1)生成結果大小(∞, 1GB),結果直接被丟棄,通過spark.driver.maxResultSize設置。
2)生成結果大小[1GB, 128MB-200KB];生成大小等於128MB-200KB,將結果以taskId爲編號存入BlockManager,然後將編號發送給Driver終端點。
3)生成結果大小(128MB-200KB, 0),直接通過Netty發送到Driver終端點。
劃分調度階段:
基於廣度優先遍歷各依賴的RDD
1)在SparkContext中提交運行時,DAGScheduler中的hadleJobSubmitted進行處理,該方法中找到最後一個RDD,並調用getParentStage方法。
2)getParentStage方法判斷rddG的依賴樹種是否存在shuffle操作。發現join操作是shuffle操作,獲取該操作的RDD是rddB和rddF。
3)使用getAncesterShuffleDependencies方法從rddB向前遍歷,發現該依賴分支上沒有shuffle操作,即沒有寬依賴。調用newOrUsedShuffleStage方法生成調度階段ShuffleMapStage0。
4)使用getAncesterShuffleDependencies方法,從rddF向前遍歷,發現該依賴分支存在寬依賴操作groupBy,以此劃分rddD,rddC爲ShuffleMapStage1,rddE,rddF爲ShuffleMapStage2。
5)最後生成rddG的ResultStage3
提交調度階段
在handleJobSubmitted方法中獲取了該例子的最後一個調度階段ReusltStage3,通過submitStage方法提交該調度階段。
在submitStage方法中,先創建作業實例,然後判斷該調度階段是否存在父調度階段,由於ReusltStage3有兩個父調度階段ShuffleMapStage0和ShuffleMapStage2,所以不能立即提交調度階段運行,把ReusltStage3放入到等待隊列中等待waitingStages中。
遞歸調用submitStage方法可以知道ShuffleMapStage0不存在父調度階段,而ShuffleMapStage2存在父調度階段ShuffleMapStage1,這樣ShuffleMapStage2加入到等待執行調度階段列表waitingStages中,而ShuffleMapStage0和ShuffleMapStage1兩個調度階段作爲第一次調度使用submitMissingTasks方法運行。
Executor任務執行完成時發送消息,DAGScheduler等調度器更新狀態時,檢查調度階段運行情況,如果存在執行失敗的任務,則重新提交調度階段;如果所有任務完成,則繼續提交調度階段運行。由於ReusltStage3的父調度階段沒有全部完成,第二次調度階段只提交ShuffleMapStage2運行。
當ShuffleMapStage2運行完畢之後,此時ResultStage3的父調度階段全部完成,提交該調度運行完成。
五 提交任務
- 在提交stage中,第一次調用的是ShuffleMapStage0【ShuffleMapStage0會拆分成ShuffleMapStage(0,0), ShuffleMapStage(0,1),同理ShuffleMapStage1也會拆分出兩個任務】和ShuffleMapStage1,假設每個stage都只有兩個partition,ShuffleMapStage0是TaskSet0,ShuffleMapStage1是TaskSet1,每個TaskSet都有兩個任務在執行。
- TaskScheduler收到發送過來的任務集TaskSet0和TaskSet1,在submitTasks方法中分別構建TaskSetManager0和TaskSetManager1,並把它們兩放到系統的調度池,根據系統設置的調度算法進行調度(FIFO或者FAIR)
- 在TaskSchedulerImpl的resourceOffers方法中按照就近原則進行資源分配,每個任務均分配運行代碼,數據分片,處理資源。使用CoarseGrainedSchedulerBackend的launchTasks方法把任務發送到Worker節點上的CoarseGrainedExecutorBackend調用其Executor來執行任務
- ShuffleMapStage0,ShuffleMapStage1執行完畢,ShuffleMapStage2,ResultStage3會執行1-3步驟,但是ReduceStage3生成的是ResultTask
六 執行任務
當CoarseGrainedExecutorBackend接收到LaunchTask消息時,會調用Executor的launchTask方法進行處理。在Executor的launchTask方法中,初始化一個TaskRunner來封裝任務,它用於管理任務運行時的細節,再把TaskRunner對象放入到ThreadPool中去執行。
對於ShuffleMapTask, 它的計算結果會寫到BlockManager之中,最終返回給DAGScheduler的是一個MapStatus。該對象管理了ShuffleMapTask的運算結果存儲到BlockManager裏的相關存儲信息,而不是計算結果本身,這些存儲信息將會成爲下一階段的任務需要獲得的輸入數據時的依據。