Spark Standalone架構設計要點分析
Apache Spark是一個開源的通用叢集計算系統,它提供了High-level程式設計API,支援Scala、Java和Python三種程式語言。Spark核心使用Scala語言編寫,通過基於Scala的函數語言程式設計特性,在不同的計算層面進行抽象,程式碼設計非常優秀。
RDD抽象
RDD(Resilient Distributed Datasets),彈性分散式資料集,它是對分散式資料集的一種記憶體抽象,通過受限的共享記憶體方式來提供容錯性,同時這種記憶體模型使得計算比傳統的資料流模型要高效。
計算抽象重點內容
在描述Spark中的計算抽象,我們首先需要了解如下幾個概念:
●Application
使用者編寫的Spark程式,完成一個計算任務的處理。它是由一個Driver程式和一組運行於Spark叢集上的Executor組成。
●Job
使用者程式中,每次呼叫Action時,邏輯上會生成一個Job,一個Job包含了多個Stage。
●Stage
Stage包括兩類:ShuffleMapStage和ResultStage,如果使用者程式中呼叫了需要進行Shuffle計算的Operator,如groupByKey等,就會以Shuffle為邊界分成ShuffleMapStage和ResultStage。
●TaskSet
基於Stage可以直接對映為TaskSet,一個TaskSet封裝了一次需要運算的、具有相同處理邏輯的Task,這些Task可以平行計算,粗粒度的排程是以TaskSet為單位的。
●Task
Task是在物理節點上執行的基本單位,Task包含兩類:ShuffleMapTask和ResultTask,分別對應於Stage中ShuffleMapStage和ResultStage中的一個執行基本單元。
下面,我們看一下,上面這些基本概念之間的關係,如下圖所示:
上圖,為了簡單,每個Job假設都很簡單,並且只需要進行一次Shuffle處理,所以都對應2個Stage。實際應用中,一個Job可能包含若干個Stage,或者是一個相對複雜的Stage DAG。
在Standalone模式下,預設使用的是FIFO這種簡單的排程策略,在進行排程的過程中,大概流程如下圖所示:
從使用者提交Spark程式,最終生成TaskSet,而在排程時,通過TaskSetManager來管理一個TaskSet(包含一組可在物理節點上執行的Task),這裡面TaskSet必須要按照順序執行才能保證計算結果的正確性,因為TaskSet之間是有序依賴的(上溯到ShuffleMapStage和ResultStage),只有一個TaskSet中的所有Task都執行完成後,才能排程下一個TaskSet中的Task去執行。
叢集模式
Spark叢集在設計的時候,並沒有在資源管理的設計上對外封閉,而是充分考慮了未來對接一些更強大的資源管理系統,如YARN、Mesos等,所以Spark架構設計將資源管理單獨抽象出一層,通過這種抽象能夠構建一種適合企業當前技術棧的外掛式資源管理模組,從而為不同的計算場景提供不同的資源分配與排程策略。Spark叢集模式架構,如下圖所示:
上圖中,Spark叢集Cluster Manager目前支援如下三種模式:
●Standalone模式
Standalone模式是Spark內部預設實現的一種叢集管理模式,這種模式是通過叢集中的Master來統一管理資源,而與Master進行資源請求協商的是Driver內部的StandaloneSchedulerBackend(實際上是其內部的StandaloneAppClient真正與Master通訊),後面會詳細說明。
●YARN模式
YARN模式下,可以將資源的管理統一交給YARN叢集的ResourceManager去管理,選擇這種模式,可以更大限度的適應企業內部已有的技術棧,如果企業內部已經在使用Hadoop技術構建大資料處理平臺。
●Mesos模式
隨著Apache Mesos的不斷成熟,一些企業已經在嘗試使用Mesos構建資料中心的作業系統(DCOS),Spark構建在Mesos之上,能夠支援細粒度、粗粒度的資源排程策略(Mesos的優勢),也可以更好地適應企業內部已有技術棧。
那麼,Spark中是怎麼考慮滿足這一重要的設計決策的呢?也就是說,如何能夠保證Spark非常容易的讓第三方資源管理系統輕鬆地接入進來。我們深入到類設計的層面看一下,如下圖類圖所示:
可以看出,Task排程直接依賴SchedulerBackend,SchedulerBackend與實際資源管理模組互動實現資源請求。這裡面,CoarseGrainedSchedulerBackend是Spark中與資源排程相關的最重要的抽象,它需要抽象出與TaskScheduler通訊的邏輯,同時還要能夠與各種不同的第三方資源管理系統無縫地互動。實際上,CoarseGrainedSchedulerBackend內部採用了一種ResourceOffer的方式來處理資源請求。
RPC網路通訊抽象
Spark RPC層是基於優秀的網路通訊框架Netty設計開發的,但是Spark提供了一種很好地抽象方式,將底層的通訊細節遮蔽起來,而且也能夠基於此來設計滿足擴充套件性,比如,如果有其他不基於Netty的網路通訊框架的新的RPC接入需求,可以很好地擴充套件而不影響上層的設計。RPC層設計,如下圖類圖所示:
任何兩個Endpoint只能通過訊息進行通訊,可以實現一個RpcEndpoint和一個RpcEndpointRef:想要與RpcEndpoint通訊,需要獲取到該RpcEndpoint對應的RpcEndpointRef即可,而且管理RpcEndpoint和RpcEndpointRef建立及其通訊的邏輯,統一在RpcEnv物件中管理。
啟動Standalone叢集
Standalone模式下,Spark叢集採用了簡單的Master-Slave架構模式,Master統一管理所有的Worker,這種模式很常見,我們簡單地看下Spark Standalone叢集啟動的基本流程,如下圖所示: