1. Spark運行模式
Spark的運行模式多種多樣,靈活多變,有衆多的運行模式可共選擇。這取決於集羣的實際情況,底層的資源調度既可以依賴外部資源調度框架,也可以使用Spark內置的Standalone模式。對於外部資源調度框架的支持,包括:Mesos模式、以及Hadoop的Yarn模式。本地還有locl cluster模式,下面分別講解。
1.1 standalone
- Standalone模式使用Spark自帶的資源調度框架
- 採用Master/Slaves的典型架構,選用ZooKeeper來實現Master的HA
- 該模式主要的節點有Client節點、Master節點和Worker節點。其中Driver既可以運行在Master節點上中,也可以運行在本地Client端。當用spark-shell交互式工具提交Spark的Job時,Driver在Master節點上運行;當使用spark-submit工具提交Job或者在Eclips、IDEA等開發平臺上使用”new SparkConf.setManager(“spark://master:7077”)”方式運行Spark任務時,Driver是運行在本地Client端上的
- SparkContext連接到Master,向Master註冊並申請資源(CPU Core 和Memory)
- Master根據SparkContext的資源申請要求和Worker心跳週期內報告的信息決定在哪個Worker上分配資源,然後在該Worker上獲取資源,然後啓動StandaloneExecutorBackend;
- StandaloneExecutorBackend向SparkContext註冊;
- SparkContext將Applicaiton代碼發送給StandaloneExecutorBackend;並且SparkContext解析Applicaiton代碼,構建DAG圖,並提交給DAG Scheduler分解成Stage(當碰到Action操作時,就會催生Job;每個Job中含有1個或多個Stage,Stage一般在獲取外部數據和shuffle之前產生),然後以Stage(或者稱爲TaskSet)提交給Task Scheduler,Task Scheduler負責將Task分配到相應的Worker,最後提交給StandaloneExecutorBackend執行;
- StandaloneExecutorBackend會建立Executor線程池,開始執行Task,並向SparkContext報告,直至Task完成
- 所有Task完成後,SparkContext向Master註銷,釋放資源
1.2 yarn
- Spark on YARN模式根據Driver在集羣中的位置分爲兩種模式:一種是YARN-Client模式,另一種是YARN-Cluster(或稱爲YARN-Standalone模式)
- Yarn-Client模式中,Driver在客戶端本地運行,這種模式可以使得Spark Application和客戶端進行交互,因爲Driver在客戶端,所以可以通過webUI訪問Driver的狀態,默認是http://hadoop1:4040訪問,而YARN通過http:// hadoop1:8088訪問
- Spark Yarn Client向YARN的ResourceManager申請啓動Application Master。同時在SparkContent初始化中將創建DAGScheduler和TASKScheduler等,由於我們選擇的是Yarn-Client模式,程序會選擇YarnClientClusterScheduler和YarnClientSchedulerBackend
- ResourceManager收到請求後,在集羣中選擇一個NodeManager,爲該應用程序分配第一個Container,要求它在這個Container中啓動應用程序的ApplicationMaster,與YARN-Cluster區別的是在該ApplicationMaster不運行SparkContext,只與SparkContext進行聯繫進行資源的分派
- Client中的SparkContext初始化完畢後,與ApplicationMaster建立通訊,向ResourceManager註冊,根據任務信息向ResourceManager申請資源(Container)
- 一旦ApplicationMaster申請到資源(也就是Container)後,便與對應的NodeManager通信,要求它在獲得的Container中啓動CoarseGrainedExecutorBackend,CoarseGrainedExecutorBackend啓動後會向Client中的SparkContext註冊並申請Task
- client中的SparkContext分配Task給CoarseGrainedExecutorBackend執行,CoarseGrainedExecutorBackend運行Task並向Driver彙報運行的狀態和進度,以讓Client隨時掌握各個任務的運行狀態,從而可以在任務失敗時重新啓動任務
- 應用程序運行完成後,Client的SparkContext向ResourceManager申請註銷並關閉自己
1.3 Spark Cluster
- Spark Yarn Client向YARN中提交應用程序,包括ApplicationMaster程序、啓動ApplicationMaster的命令、需要在Executor中運行的程序等
- ResourceManager收到請求後,在集羣中選擇一個NodeManager,爲該應用程序分配第一個Container,要求它在這個Container中啓動應用程序的ApplicationMaster,其中ApplicationMaster進行SparkContext等的初始化
- ApplicationMaster向ResourceManager註冊,這樣用戶可以直接通過ResourceManage查看應用程序的運行狀態,然後它將採用輪詢的方式通過RPC協議爲各個任務申請資源,並監控它們的運行狀態直到運行結束
- 一旦ApplicationMaster申請到資源(也就是Container)後,便與對應的NodeManager通信,要求它在獲得的Container中啓動CoarseGrainedExecutorBackend,CoarseGrainedExecutorBackend啓動後會向ApplicationMaster中的SparkContext註冊並申請Task。這一點和Standalone模式一樣,只不過SparkContext在Spark Application中初始化時,使用CoarseGrainedSchedulerBackend配合YarnClusterScheduler進行任務的調度,其中YarnClusterScheduler只是對TaskSchedulerImpl的一個簡單包裝,增加了對Executor的等待邏輯等
- ApplicationMaster中的SparkContext分配Task給CoarseGrainedExecutorBackend執行,CoarseGrainedExecutorBackend運行Task並向ApplicationMaster彙報運行的狀態和進度,以讓ApplicationMaster隨時掌握各個任務的運行狀態,從而可以在任務失敗時重新啓動任務
- 應用程序運行完成後,ApplicationMaster向ResourceManager申請註銷並關閉自己
2. Spark運行流程及特點
- 構建Spark Application的運行環境,啓動SparkContext
- SparkContext向資源管理器(可以是Standalone,Mesos,Yarn)申請運行Executor資源,並啓動StandaloneExecutorbackend,
- Executor向SparkContext申請Task
- SparkContext將應用程序分發給Executor
- SparkContext構建成DAG圖,將DAG圖分解成Stage、將Taskset發送給Task Scheduler,最後由Task Scheduler將Task發送給Executor運行
- Task在Executor上運行,運行完釋放所有資源
Spark運行特點:
- 每個Application獲取專屬的executor進程,該進程在Application期間一直駐留,並以多線程方式運行Task。這種Application隔離機制是有優勢的,無論是從調度角度看(每個Driver調度他自己的任務),還是從運行角度看(來自不同Application的Task運行在不同JVM中),當然這樣意味着Spark Application不能跨應用程序共享數據,除非將數據寫入外部存儲系統
- Spark與資源管理器無關,只要能夠獲取executor進程,並能保持相互通信就可以了
- 提交SparkContext的Client應該靠近Worker節點(運行Executor的節點),最好是在同一個Rack裏,因爲Spark Application運行過程中SparkContext和Executor之間有大量的信息交換
- Task採用了數據本地性和推測執行的優化機制
3. RDD運行流程
RDD在Spark中運行大概分爲以下三步:
- 創建RDD對象
- DAGScheduler模塊介入運算,計算RDD之間的依賴關係,RDD之間的依賴關係就形成了DAG
- 每一個Job被分爲多個Stage。劃分Stage的一個主要依據是當前計算因子的輸入是否是確定的,如果是則將其分在同一個Stage,避免多個Stage之間的消息傳遞開銷
示例圖如下: