在闡明了spark的master的啟動流程與worker啟動流程。接下繼續執行的就是worker上的executor程序了,本文繼續分析整個executor的啟動與任務送出流程
送出一個任務到叢集通過的是spark-submit
通過啟動腳本的方式啟動它的主類,這裡以wordcount為例子
<code>spark-submit --class cn.apache.spark.wordcount</code>
bin/spark-clas -> org.apache.spark.deploy.sparksubmit 調用這個類的main方法
dorunmain方法中傳進來一個自定義spark應用程式的main方法
<code>class cn.apache.spark.wordcount</code>
通過反射拿到類的執行個體的引用<code>mainclass = utils.classforname(childmainclass)</code>
在通過反射調用<code>class cn.apache.spark.wordcount</code>的<code>main</code>方法
我們來看sparksubmit的main方法
這裡的類型是submit,調用submit方法
submit裡調用了dorunmain(),然後調用了runmain,來看runmain
最主要的流程就在這裡了,上面的代碼注釋很清楚,通過反射調用我們寫的類的main方法,大體的流程到此
sparksubmit時序圖

sparksubmit通過反射調用了我們程式的main方法後,就開始執行我們的代碼
,一個spark程式中需要建立sparkcontext對象,我們就從這個對象開始
sparkcontext的構造方法代碼很長,主要關注的地方如下
spark的構造方法主要幹三件事,建立了一個sparkenv,taskscheduler,dagscheduler,我們先來看<code>createtaskscheduler</code>裡幹了什麼
通過master的url來比對到standalone模式:然後初始化了sparkdeployschedulerbackend和taskschedulerimpl,這兩個對象很重要,是啟動任務排程的核心,然後調用了<code>scheduler.initialize(backend)</code>進行初始化
啟動taksscheduler初始化完成,回到我們的sparkcontext構造方法後面繼續調用了
<code>taskscheduler.start()</code> 啟動taksscheduler
來看start方法
這裡的backend是sparkdeployschedulerbackend調用了它的start
這裡是拼裝了啟動executor的一些參數,類名+參數 封裝成applicationdescription。最後傳給并建立appclient并調用它的start方法
appclient建立時序圖
接來下關注start方法
在start方法裡建立了與master通信的clientactor,然後會調用它的prestart方法向master注冊,接下來看它的prestart
最後會調用該方法向所有master注冊
clientactor發送來的注冊app的消息,applicationdescription,他包含了需求的資源,要求啟動的executor類名和一些參數
master的receiver
registerapplication(app)
master将接受的資訊儲存到集合并序列化後發送一個<code>registeredapplication</code>消息通知回報給clientactor,接着執行schedule()方法,該方法中會周遊workers集合,并執行launchexecutor
這裡master向worker發送啟動executor的消息
application.desc裡包含了executor類的啟動資訊
worker的receiver接受到了啟動executor的消息,appdesc對象儲存了command指令、executor的實作類和參數
<code>manager.start()</code>裡會建立一個線程
線上程中調用了<code>fetchandrunexecutor()</code>方法,我們來看該方法
這裡面進行了類名和參數的拼裝,具體拼裝過程不用關心,最終<code>builder.start()</code>會以systemruntime的方式啟動一個子程序,這個是程序的類名是coarsegrainedexecutorbackend
到此executor程序就啟動起來了
executor建立時序圖
executor程序後,就首先要執行main方法,main的代碼如下
執行了run方法
run方法中建立了coarsegrainedexecutorbackend的actor對象用于準備和driveractor通信,接着會繼續調用prestart生命周期方法
executor向driveractor發送注冊的消息
<code>driver ! registerexecutor(executorid, hostport, cores, extractlogurls)</code>
driveractor的receiver收到消息後
driveractor的receiver裡将executor資訊封裝到map中儲存起來,并發送回報消息 <code>sender ! registeredexecutor</code>
給coarsegrainedexecutorbackend
coarsegrainedexecutorbackend收到消息後建立一個executor對象用于準備任務的執行,到此executor的建立就完成了,接下來下篇介紹任務的排程。