在Standalone模式下,Spark中各個組件之間交互還是比較複雜的,但是對於一個通用的分佈式計算系統來說,這些都是非常重要而且比較基礎的交互。首先,爲了理解組件之間的主要交互流程,我們給出一些基本要點:
一個Application會啓動一個Driver
一個Driver負責跟蹤管理該Application運行過程中所有的資源狀態和任務狀態
一個Driver會管理一組Executor
一個Executor只執行屬於一個Driver的Task
核心組件之間的主要交互流程,如下圖所示:
上圖中,通過不同顏色或類型的線條,給出瞭如下6個核心的交互流程,我們會詳細說明:
橙色:提交用戶Spark程序
用戶提交一個Spark程序,主要的流程如下所示:
- 用戶spark-submit腳本提交一個Spark程序,會創建一個ClientEndpoint對象,該對象負責與Master通信交互
- ClientEndpoint向Master發送一個RequestSubmitDriver消息,表示提交用戶程序
- Master收到RequestSubmitDriver消息,向ClientEndpoint回覆SubmitDriverResponse,表示用戶程序已經完成註冊
- ClientEndpoint向Master發送RequestDriverStatus消息,請求Driver狀態
- 如果當前用戶程序對應的Driver已經啓動,則ClientEndpoint直接退出,完成提交用戶程序
總結:提交driver程序!!!!!!!!!!!!!!!!!
紫色:啓動Driver進程
當用戶提交用戶Spark程序後,需要啓動Driver來處理用戶程序的計算邏輯,完成計算任務,這時Master協調需要啓動一個Driver,具體流程如下所示:
- Maser內存中維護着用戶提交計算的任務Application,每次內存結構變更都會觸發調度,向Worker發送LaunchDriver請求
- Worker收到LaunchDriver消息,會啓動一個DriverRunner線程去執行LaunchDriver的任務
- DriverRunner線程在Worker上啓動一個新的JVM實例,該JVM實例內運行一個Driver進程,該Driver會創建SparkContext對象
總結:啓動Driver程序,創建SparkContext對象!!!!!!!!!!!!!!!!!!
紅色:註冊Application
Dirver啓動以後,它會創建SparkContext對象,初始化計算過程中必需的基本組件,並向Master註冊Application,流程描述如下:
- 創建SparkEnv對象,創建並管理一些基本組件
- 創建TaskScheduler,負責Task調度
- 創建StandaloneSchedulerBackend,負責與ClusterManager進行資源協商
- 創建DriverEndpoint,其它組件可以與Driver進行通信
- 在StandaloneSchedulerBackend內部創建一個StandaloneAppClient,負責處理與Master的通信交互
- StandaloneAppClient創建一個ClientEndpoint,實際負責與Master通信
- ClientEndpoint向Master發送RegisterApplication消息,註冊Application
- Master收到RegisterApplication請求後,回覆ClientEndpoint一個RegisteredApplication消息,表示已經註冊成功
總結:像master註冊,Application對象!!!!!!!!!!!!!!!!!!!!!
藍色:啓動Executor進程
- Master向Worker發送LaunchExecutor消息,請求啓動Executor;同時Master會向Driver發送ExecutorAdded消息,表示Master已經新增了一個Executor(此時還未啓動)
- Worker收到LaunchExecutor消息,會啓動一個ExecutorRunner線程去執行LaunchExecutor的任務
- Worker向Master發送ExecutorStageChanged消息,通知Executor狀態已發生變化
- Master向Driver發送ExecutorUpdated消息,此時Executor已經啓動
總結:master像woker發送消息,啓動Executor !!!!!!!!!!!!!!!!!!!!!
粉色:啓動Task執行
- StandaloneSchedulerBackend啓動一個DriverEndpoint
- DriverEndpoint啓動後,會週期性地檢查Driver維護的Executor的狀態,如果有空閒的Executor便會調度任務執行
- DriverEndpoint向TaskScheduler發送Resource Offer請求
- 如果有可用資源啓動Task,則DriverEndpoint向Executor發送LaunchTask請求
- Executor進程內部的CoarseGrainedExecutorBackend調用內部的Executor線程的launchTask方法啓動Task
- Executor線程內部維護一個線程池,創建一個TaskRunner線程並提交到線程池執行
總結:Executor 啓動 task 執行 程序 !!!!!!!!!!!!!!!!!!!!!
綠色:Task運行完成
- Executor進程內部的Executor線程通知CoarseGrainedExecutorBackend,Task運行完成
- CoarseGrainedExecutorBackend向DriverEndpoint發送StatusUpdated消息,通知Driver運行的Task狀態發生變更
- StandaloneSchedulerBackend調用TaskScheduler的updateStatus方法更新Task狀態
- StandaloneSchedulerBackend繼續調用TaskScheduler的resourceOffers方法,調度其他任務運行