轉載:Spark的運行架構分析(一)

轉載:Spark的運行架構分析(一)

1:Spark的運行模式

2:Spark中的一些名詞解釋

3:Spark的運行基本流程

4:RDD的運行基本流程

一:Spark的運行模式

Spark的運行模式多種多樣,靈活多變,部署在單機上時,既可以用本地模式運行,也可以用偽分布模式運行,而當以分布式集群的方式部署時,也有眾多的運行模式可供選擇,這取決于集群的實際情況,底層的資源調度即可以依賴外部資源調度框架,也可以使用Spark內建的Standalone模式。對于外部資源調度框架的支持,目前的實現包括相對穩定的Mesos模式,以及還在持續開發更新中的hadoop YARN模式。

在實際應用中,Spark應用程序的運行模式取決于傳遞給SparkContext 的Master環境變量的值,個別模式還需要依賴輔助的程序接口來配合使用,目前所支持的Master環境變量由特定的字符串或URL組成,如下:

Local[N]:本地模式,使用N個線程

Local cluster[worker,core,Memory]:偽分布模式,可以配置所需要啟動的虛擬工作節點的數量,以及每個工作節點所管理的CPU數量和內存尺寸

Spark://hostname:port :Standalone模式,需要部署Spark到相關節點,URL為Spark Master主機地址和端口

Mesos://hostname:port:Mesos模式,需要部署Spark和Mesos到相關節點,URL為Mesos主機地址和端口

YARN standalone/YARN cluster:YARN模式之一,主程序邏輯和任務都運行在YARN集群中

YARN client:YARN模式二,主程序邏輯運行在本地,具體任務運行在YARN集群中

二:Spark的一些名詞解釋

Application:指的是用戶編寫的Spark應用程序,內含了一個Driver功能的代碼和分布在集群中多個節點上運行的Executor代碼;

Driver Program:Spark中的Driver即運行上述Application的main()函數并且創建SparkContext,其中創建SparkContext的目的是為了準備Spark應用程序的運行環境。在Spark中由SparkContext負責和ClusterManager通信,進行資源的申請、任務的分配和監控等;當Executor部分運行完畢后,Driver負責將SparkContext關閉。通常用SparkContext代表Driver

Executor:Application運行在Worker節點上的一個進程,該進程負責運行Task,并且負責將數據存在內存或者磁盤上,每個Application都有各自獨立的一批Executor。在Spark on Yarn模式下,其進程名稱為CoarseGrainedExecutorBackend,類似于Hadoop MapReduce中的YarnChild。一個CoarseGrainedExecutorBackend進程有且僅有一個executor對象,它負責將Task包裝成taskRunner,并從線程池中抽取出一個空閑線程運行Task。每個CoarseGrainedExecutorBackend能并行運行Task的數量就取決于分配給它的CPU的個數了

Cluster Mananger:指的是在集群上獲取資源的外部服務,目前有:

Standalone:Spark原生的資源管理,由Master負責資源的分配;
Hadoop Yarn:由YARN中的ResourceManager負責資源的分配;

Worker:集群中任何可以運行Application代碼的節點,類似于YARN中的NodeManager節點。在Standalone模式中指的就是通過Slave文件配置的Worker節點,在Spark on Yarn模式中指的就是NodeManager節點

Job:包含多個Task組成的并行計算,往往由Spark Action催生,一個JOB包含多個RDD及作用于相應RDD上的各種Operation

Starge:每個Job會被拆分很多組Task,每組任務被稱為Stage,也可稱TaskSet,一個作業分為多個階段

Task:被送到某個Executor上的工作任務

三:Spark的基本運行流程

Spark架構圖

1:Spark的基本運行流程如下圖:

Spark工作流程

(1):構建Spark Application的運行環境,啟動SparkContext

(2):SparkContext向資源管理器(可以是Standalone,Mesos,Yarn)申請運行Executor資源,并啟動Standalone Executorbackend,Executor向SparkContext申請Task

(3):SparkContext將應用程序分發給Executor

(4):SparkContext構建成DAG圖,將DAG圖分解成Stage、將Taskset發送給TaskScheduler,最后由Task Scheduler將Task發送給Executor運行

(5):Task在Executor上運行,運行完釋放所有資源

總結:
1 sparkcontext由用戶程序啟動,是程序運行的總入口;
2 sparkcontext初始化過程中分別創建DAGScheduler進行作業調度和TaskScheduler進行任務調度,這兩級調度模塊;
3 sparkcontext通過集群管理與Executor通信;
4 所以一般流程是:RDD-->DAGScheduler-->taskset發送到TastScheduler-->worker執行;

DAGScheduler模塊是基于任務調度的高層調度模塊,它將作業拆分成具有依賴關系的多個調度階段(通常根據shuffle來劃分),每個階段(parse)構建出一組具體的任務(taskset),然后以taskset形式提交給任務調度模塊具體執行。DAGScheduler負責任務的邏輯調度,而TaskScheduler負責任務的物理調度;

與DAGScheduler交互的接口有taskScheduler和SchedulerBackend;taskScheduler的實現主要是用于DAGScheduler交互,負責具體任務的調度與運行;
SchedulerBackend的實現是與底層資源調度系統交互,配合taskScheduler實現具體任務的資源分配;
在提交任務和更新狀態時,taskScheduler都會調用backend的receiveOffers函數發起一次資源調度;

Executor:任務的運行都在executor上,其中為每一個任務創建一個taskTunner類,然后交給線程池運行,具體過程:創建線程---創建任務列表---創建taskRunner---放入任務列表---提交線程池運行。

2:Spark運行架構的特點

(1):每個Application獲取專屬的executor進程,該進程在Application期間一直駐留,并以多線程方式運行Task。這種Application隔離機制是有優勢的,無論是從調度角度看(每個Driver調度他自己的任務),還是從運行角度看(來自不同Application的Task運行在不同JVM中),當然這樣意味著Spark Application不能跨應用程序共享數據,除非將數據寫入外部存儲系統

(2):Spark與資源管理器無關,只要能夠獲取executor進程,并能保持相互通信就可以了

(3):提交SparkContext的Client應該靠近Worker節點(運行Executor的節點),最好是在同一個機架里,因為Spark Application運行過程中SparkContext和Executor之間有大量的信息交換,如果在遠程集群中運行,最好使用RPC將SparkContext提交給集群,不要遠離Worker運行SparkContext

(4)Task采用了數據本地性和推測執行的優化機制

3:DAGscheduler

DAGScheduler把一個Spark作業轉換成Stage的DAG(Directed Acyclic Graph有向無環圖),根據RDD和Stage之間的關系找出開銷最小的調度方法,然后把Stage以TaskSet的形式提交給TaskScheduler,下圖展示了DAGScheduler的作用:

DAGscheduler

4:TaskScheduler

DAGScheduler決定了Task的理想位置,并把這些信息傳遞給下層的TaskScheduler。此外,DAGScheduler還處理由于Shuffle數據丟失而導致的失敗,還有可能需要重新提交運行之前的Stage(非Shuffle數據丟失導致的Task失敗由TaskScheduler處理)

TaskScheduler維護所有TaskSet,當Executor向Driver發生心跳時,TaskScheduler會根據資源剩余情況分配相應的Task。另外TaskScheduler還維護著所有Task的運行標簽,重試失敗的Task。下圖展示了TaskScheduler的作用:

TaskScheduler

在不同運行模式中任務調度器具體為:

(1):Spark on Standalone模式為TaskScheduler;

(2):YARN-Client模式為YarnClientClusterScheduler

(3):YARN-Cluster模式為YarnClusterScheduler

四:RDD的運行基本流程

那么RDD在Spark中怎么運行的?大概分為以下三步:

1:創建RDD對象

2:DAGScheduler模塊介入運算,計算RDD之間的依賴關系,RDD之間的依賴關系就形成了DAG

3:每一個Job被分為多個Stage。劃分Stage的一個主要依據是當前計算因子的輸入是否是確定的,如果是則將其分在同一個Stage,避免多個Stage之間的消息傳遞開銷。

image

備注:構建DAG---將DAG圖分成任務階段,提交準備好的stage---通過集群管理器啟動任務---執行任務

案例

以下面一個按 A-Z 首字母分類,查找相同首字母下不同姓名總個數的例子來看一下 RDD 是如何運行起來的

步驟 1

步驟 1 :創建 RDD 上面的例子除去最后一個 collect 是個動作,不會創建 RDD 之外,前面四個轉換都會創建出新的 RDD 。因此第一步就是創建好所有 RDD( 內部的五項信息 ) 。

步驟 2 :創建執行計劃 Spark 會盡可能地管道化,并基于是否要重新組織數據來劃分 階段 (stage),例如本例中的 groupBy() 轉換就會將整個執行計劃劃分成兩階段執行。最終會產生一個 DAG(directed acyclic graph ,有向無環圖 )作為邏輯執行計劃。

步驟 2

步驟 3 :調度任務將各階段劃分成不同的 任務 (task),每個任務都是數據和計算的合體。在進行下一階段前,當前階段的所有任務都要執行完成。因為下一階段的第一個轉換一定是重新組織數據的,所以必須等當前階段所有結果數據都計算出來了才能繼續。

假設本例中的 hdfs://names 下有四個文件塊,那么 HadoopRDD 中 partitions 就會有四個分區對應這四個塊數據,同時 preferedLocations會指明這四個塊的最佳位置。現在,就可以創建出四個任務,并調度到合適的集群結點上。

image
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容