一行Spark程式碼的誕生記(深度剖析Spark架構)

一名叫大蕉的程式設計師發表於2017-08-11

大家好,我是一行Spark程式碼,我叫小小小蕉,不知道為毛,我爸爸大蕉和我媽媽大大蕉把我生的又瘦又長。長這樣。


val sssjiao = new SparkContext(new SparkConf().setAppName("sssjiao").setMaster("yarn-cluster")).parallelize(Array(""));


我真的,不知道怎麼說,好長好長啊。。總有小夥伴對著我說:

問君何不乘風起 扶搖直上九萬里。


說出來不怕嚇著你,其實我一個字都看不懂。





作為一行普通的程式碼,我也開始思考碼生的三大問題,我是誰,我從哪裡來,要到哪裡去。


我從我從哪裡來,開始講我的故事吧。





我從哪裡來?


這有什麼好說的,出自我爸爸大大蕉之手,就醬。


本文終。


噹噹噹,你以為就這樣結束了嗎?不可能的。我長得這麼細這麼長,其實我是由三個部分組成的。分別是SparkConf,SparkContext,RDD[String],從程式碼層面來說,就是定義了一個SparkConf的配置,來生成一個SparkContext上下文,然後用這個SparkContext來對陣列進行序列化,我就被產生出來啦。


但是我今天不僅僅是想介紹這麼淺層的來源,畢竟爸比媽咪生得我那麼辛苦是吧?


(要開始Spark on yarn的深度剖析了)



大大蕉:yarn兄,我要生一個兒子,oh不我要產生一個Spark任務了,能幫忙撥 點行政資源不?


yarn :啥玩意,你想幹啥?要尊貴的cluster模式還是平民的client模式?


大大蕉:這兩個有啥差別?我頭胎。


yarn :client就你用你自己粗糙的Driver,cluster模式就我給你分配一個高配置又漂亮的Driver。


大大蕉:那行,給我來個尊貴的cluster吧。


yarn :等著。


yarn :歪,ResourceManager嗎(管資源的,下面簡稱RM)?你那邊不是在管資源嗎?我們這有貨嗎?趕緊給我空運一個高配的機器,嗯對,用來跑Driver和ApplicationMaster的,嗯對對對,我們這邊有人快生了。對,急急急,這輩子就這要一次最急。


RM :知道了(一臉嫌棄懶洋洋)。


過了0.00001ms,對於CPU來說過了好久了


RM :NodeManage(每臺機器的管家,下面簡稱NM),歪,根據記錄你那裡的配置恰好夠用,你那裡的Container1容器我徵用了,就這樣。


NM :我R。。。


RM :yarn老哥,給你那個名字為container-1的容器吧,他的地址和配置資訊(CPU,記憶體)在這,你收好了。


yarn的最小分配單位為Container


yarn :好的,非常感謝,後面有事情還麻煩你。


yarn :大大蕉嗎?Container拿到了,就是Container1,自己去看看怎麼生吧。


大大蕉:好的。掰。


大大蕉:(自言自語)根據說明書,先啟動一個ApplicationMaster,名字叫做sssjiao,用來管理這個Job和Container。再先啟動一個Driver,來管理DAGScheduler(有向無環圖管理)和TaskScheduler(任務排程管理),BlockManagerMaster(資料塊管理的Master)。咦,那我去哪跑任務呢?還差一些Worker工作站啊。


Spark將一個大的任務拆成一個有向無環圖,來表示依賴關係。


大大蕉:歪。yarn嗎?嗯是我。我這好像還差點東西啊。。我還需要一些Container來做我的Worker啊,不然我兒子生完往哪放啊?


yarn :知道了知道了,不會一次說完嗎?真討厭。


大大蕉:我。。。我™也不知道需要這個啊。


yarn :歪。RM嗎?嗯又是我。我需要一批Container。嗯對高配那種。對,急急急,這輩子就這一次最急。


RM :知道了。(不耐煩)


RM :NM-A,NM-B,NM-C,NM-D,你們幾個的資源我都徵用了。


NM界一臉懵逼,都感覺自己被搶劫了。。


RM :歪,yarn老哥嗎?資源都ok了。ContainerA,ContainerB,ContainerC,ContainerD。


yarn :好嘞。


yarn :大大蕉。資源拿到了,資訊我裝在信封裡了,你拿好吧。


大大蕉:嗯,我還想問一下,後面的(電話那頭傳來嘟嘟嘟結束通話的聲音)。步、驟、要、怎、麼、走。算了還是自己看說明書吧。


首先在Container裡面啟動一個或者多個Executor,然後啟動一些jvm和BlockManager。好了現在Driver、Master和Worker都有了,完事具備,只欠東西南北風了。


到這裡,SparkContext算是初始化完了。


大大蕉抓著頭髮,一臉茫然地看著面前這堆玩意,要怎麼玩。。。


誒,再看看說明書吧,看看有沒有說怎麼玩。(大蕉自言自語道)


突然空氣中響起了旁白:切分、分配、切分、分配。


對!這個job可以先用DAGScheduler進行stage切分。


切分完然後用TaskScheduler進行任務排程分配。所以一個Job就被切分成很多個stage,封裝成很多個TaskSet,然後每次Executor來請求任務的時候,就給他們分配一個,所有的Executor執行完成後又向TaskScheduler報告進度。


Task失敗了?報告TaskScheduler。從頭開始重新跑。

Task太慢了?TaskSchduler找多一個Executor並行跑,誰先跑完就用誰(好殘忍)

Stage掛了?TaskScheduler報告DAGScheduler重新進行Stage拆分,看看是從當前開始重跑還是要用從父stage重跑。


好了到現在,小小小蕉我,還沒有被產生出來。。

然後SparkContext就我的前輩Array("")進行序列化,然後根據key,也就是每個字串進行分割槽,分割槽完之後把分割槽資訊和對應的Executor儲存起來。然後呢根據分割槽資訊把資料傳送到Executor那邊去。所以我的本體RDD是在Driver的,但是我被分成很多份很小份很小份放在Exector裡面的。


我是誰?


我是一個RDD。全名 RDD(Reilient Distributed DataSets)彈性分散式資料集。RDD的具體描述在這裡邊。

小飛象小飛象飛吖飛No.6


我要到哪裡去?


我後面的任務就是進行具體程式的執行,一個job一個job,一個stage一個stage。


這裡再深入,就是從編譯完的.class檔案,用JVM的ClassLoader類載入器,載入完變成一個真正的類,然後再又JVM編譯成機器碼,在堆裡開闢一點記憶體初始化一個String物件,在棧裡開闢一點記憶體初始化一個指標。


然而跑完之後呢,我又將何去何從呢?


然後10M以下的就直接放在結果返回給TaskScheduler啦。

如果在10M以上的,就放到某個BlockManage,只返回BlockId了。


通知TaskScheduler說跑完啦。


然後TaskScheduler就通知DAGScheduler說跑完啦。


然後DAGScheduler就通知SparkContext說跑完啦。


然後SparkContext就通知Driver跑完啦。


然後SparkContext就準備要stop了。


大大蕉 :歪,yarn嗎?我兒子生完了,資源都還給你把。


yarn :好。


yarn :歪。RM嗎?剛剛申請的資源用完了,你把它們標記為可用把。


虛擬機器 :這行又瘦又長的叫sssjiao的程式碼是誰啊。。好像被人丟在這了,誒當垃圾回收了吧,然後就給小小小蕉臉上蓋上了一個待回收的印子♻️。


過了不久,小小小蕉就被GC(Garbage Collection)回收了,但是它臉上洋溢著笑容,它,是快樂的。



這就是小小小蕉快快樂樂的一生。

附上之前的好幾篇Spark文章哈。


小飛象小飛象飛吖飛No.6

Spark你一定學得會(一)No.7

Spark你一定學得會(二)No.8

Spark你一定學得會(三)No.10






如果覺得還不錯呢,就幫忙點贊評論分享一下啦,是對我最大的支援,感謝各位讀者小夥伴,哇咔咔(づ ̄3 ̄)づ╭❤~。


微信公眾號:一名叫大蕉的程式設計師


相關文章