標籤:核心 spark 架構解密
只有知道核心架構的基礎上,才知道為什麼要這樣寫程式?
手工繪圖來解密Spark核心架構
通過案例來驗證Spark核心架構
Spark架構思考
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
==========Spark Runtime的幾個概念============
下載下來運行,基本都是standalone模式,如果掌握了standalone,則yarn和mesos,以後不做特別說明,一律是standalone模式
application=driver+executor,executor是具體處理資料分區,裡面是線程池並發的處理資料分區
Drvier(代碼部分就是SparkConf+SparkContext):運行程式的時候,具有main方法,並且建立了SparkContext這樣的一個環境對象,是整個程式運行調度的核心,它不是資源調度。有高層調度,底層調度。運行對象的時候,會向Master註冊當前的程式。Master會分配資源,會有一系列的job,產生stage,交給task scheduler,發給executor,運行之後把結果返回給Drvier,然後關閉SparkContext。
executor:運行在Worker所在的節點,為當前應用程式開啟的進程裡面的對象,通過線程池並發執行和線程複用。分布在各個叢集上的代碼,但是要啟動並執行話,這個代碼得發過去。一個Worker一般只開闢一個executor,當然也可以配置多個。具體多少excutor,在最佳化的時候再講解。
下面的代碼是Drvier,裡面有DAG
val conf = new SparkConf()//建立SparkConf對象
conf.setAppName("My First Spark App!")//設定應用程式的名稱,在程式啟動並執行監控介面可以看到名稱
conf.setMaster("local")//此時程式在本地運行,不需要安裝Spark叢集
val sc = new SparkContext(conf)//通過建立SparkContext對象,通過傳入SparkConf執行個體來定製Spark啟動並執行具體參數和配置資訊
然後是產生RDD,就是executor具體執行的代碼,就是下面的代碼
val lines = sc.textFile("F:/安裝檔案/作業系統/spark-1.6.0-bin-hadoop2.6/README.md", 1)
==========Spark Cluster的幾個概念============
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
Cluster Manager:叢集中擷取資源的外部服務,Spark Application的運行不依賴於Cluster Manager。Spark應用程式註冊給Cluster Manager,比如Master註冊成功,Cluster Manager已經給Master分配好資源。此時運行程式根本不需要Cluster Manager。這是粗粒度的運行方式。
Master的機器配置要很好。
Woker:可以具體運行作業碼的節點。Woker本身不會運行程式的代碼,它是管理當前node的記憶體CPU等資源的使用狀況的,它會接受Master分配計算資源(executor,在新的進程中分配 )指令,通過executor runner啟動新進程,進行裡面有excutor,Worker是工頭,Cluster Manager是專案經理,Worker下面有好多人幹活的。
Worker會不會在發心跳的時候向Master彙報當前機器的記憶體和CPU資訊?
不會!Worker向Master發心跳只有WorkerID。
如果不發,Master怎麼知道它的資源呢?
應用程式註冊成功,Master分配資源的時候就知道了
Job:就是包括了一些列Task的並行計算。一般需要Action觸發。Action不會產生RDD。Action前面有RDD,是transfoemation,是lazy層級的。
Spark快不是因為基於記憶體。最基本是調度,然後是容錯,才是精髓,還有其它好多內容。
窄依賴,除了一對一,range層級的,固定個數,不會隨著規模的大小而變化,比如原來3個,就算加到100台,還是3個MapPartitionRDD。
Stage內部計算邏輯完全一樣,只是計算的資料不同罷了。這就是分布式並行計算,是大資料的基本精髓點。
一個Partition是不是固定128M?不是,因為最後的一條資料跨兩個Block。
一個application裡面可以有多個jobs,一般一個action操作對應一個job。其它情況比如checkpoint也會導致job。
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
==========Spark核心架構解密繪圖============
~~~1、Driver~~~
專門提交Spark程式的機器(Driver,它的核心是SparkContext),這台機器一定和Spark Cluster在同樣的網路環境中,且其配置和普通的Worker一致。因為會不停的互動,所以網路在一起。該機器可能會有其它企業級的J2EE程式等。這個機器有appication、各種依賴的外部資源(例如.so、file等等)。在此基礎上,使用spark-submit來運行,可以配置各種運行時的參數,比如memory、cores等等。實際生產環境下不會手工spark-submit來運行,一般會寫指令碼,用crontab自動化配置和提交程式。提交Spark程式的機器,必須要安裝Spark,只不過是這裡安裝的Spark不屬於叢集!!!Driver單列的時候一般不做HA,但是Master形式的時候,用--supervise模式,它會自動啟動Driver。
(Spark程式的運行有兩種模式,client模式和cluster模式,預設建議使用client模式,因為可以看到很多日誌資訊,但是實際運用,Cluster)
之前寫程式提交給Master,因為現在只有3台機器,所以,一般Driver和Worker是分開的。
~~~2、SparkContext~~~
最重要做三件事情:建立DAGScheduler、TaskScheduler、SchedulerBackend
在執行個體化的的過程Register當前的程式給Master,Master接受註冊,如果沒有問題,Master會為當前程式分配AppID並分配計算資源
~~~3、SparkCluster~~~
Master接受目前使用者提交的作業,給Worker為當前程式的資源,每個Worker所在節點預設為當前程式分配一個Executor,在Executor中通過線程池並發執行
slaves老師機器配置的Worker1、2、3、4就是這個意思
我的配置的是Master、Woker1、2,因為我的電腦配置低
Master分配多少資源來源:1、spark-env.sh和spark-defaults.sh設定的參數;2、submit提供的參數;3、程式中SparkConf提供的參數
Worker通過一個Proxy為ExecutorRunner的對象執行個體遠程啟動ExecutorBackend
ExecutorBackend裡面有Executor的線程池ThreadPool
實際在工作的時候會通過TaskRunner來封裝Task
TaskRunner是一個runner的介面,然後從ThreadPool中擷取一條線程執行Task,執行完後,線程被回收複用
上面就是分配資源的部分,然後通過Action來觸發Job,這個時候DAGScheduler登場了
~~~4、Job~~~
一般情況下當通過Action觸發Job時,SparkContext會通過DAGScheduler來把Job中的RDD構成的DAG劃分成不同的Stage,每個Stage內部是一系列內部邏輯完全相同,但是處理資料不同的Tasks構成了TaskSet
~~~5、TaskScheduler ~~~
TaskScheduler和SchedulerBacked具體Task運行(遵循資料本地性)
~~~5、Task類型~~~
最後Stage的Task稱為ResultTask,產生Job結果
其它前面的Stage的Task都是ShuffleMapTask為下一階段的Stage做資料準備,相當於MapReduce的Mapper,知識 是更精緻和高效的實現
整個Spark啟動並執行精髓就是DAGScheduler把Job劃分成不同的Stage,提交TaskSet給TaskScheduler,進而提交給Executor進行(符合資料本地行),每個Task會計算RDD中的一個Partition,基於該Partition來具體執行我們定義的一系列同一個Stage內部的函數,以此類推,直到整個程式運行完成!
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M01/7A/C3/wKioL1a0GIWBqQMtAAlClnFVfUw973.jpg" title="Spark核心架構圖.jpg" alt="wKioL1a0GIWBqQMtAAlClnFVfUw973.jpg" />
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
王家林老師名片:
中國Spark第一人
新浪微博:http://weibo.com/ilovepains
公眾號:DT_Spark
部落格:http://blog.sina.com.cn/ilovepains
手機:18610086859
QQ:1740415547
郵箱:[email protected]
本文出自 “一枝花傲寒” 部落格,謝絕轉載!
Spark核心架構解密(DT大資料夢工廠)