本文主要講解Dstream 如何生成RDD以及如何驅動RDD的調用的?
(1)從Dstream.print()開始
將數據打印出來,取前面幾條,最後調用的是:
而regester中是直接將結果作爲輸出ssc.graph.addOutputStream(this)
上一節中我們知道,JobGenertor會掉用generatedJob來定期啓動time調用job.
也就是說,是 DStreamGraph
繼續調用了每 outputStream
的 generateJob(time)
方法 —— 而我們知道,只有 ForEachDStream 是 outputStream,所以將調用 ForEachDStream
的 generateJob(time)
方法.比如調用print的時候會調用ForeachDstream的generatoeJob,其中會調用parent.getOrCompute(time)àcomputer(time)方法,compute(time) 的具體實現裏,就很簡單了:
- (1) 獲取 parent DStream 在本 batch 裏對應的 RDD 實例
- (2) 以這個 parent RDD 和本次 batch 的 time 爲參數,調用 foreachFunc(parentRDD, time) 方法
(2)上面是action的流程,對於transformation又是如何的?
MappedDstream的compute方法
override def compute(validTime: Time): Option[RDD[U]] = {
parent.getOrCompute(validTime).map(_.map[U](mapFunc))
}
可以看到,首先在構造函數裏傳入了兩個重要內容:
- parent,是本 MappedDStream 上游依賴的 DStream
- mapFunc,是本次 map() 轉換的具體函數
- 在前文 [DStream, DStreamGraph 詳解](1.1 DStream, DStreamGraph 詳解.md) 中的 quick example 裏的 val pairs = words.map(word => (word, 1)) 的 mapFunc 就是 word => (word, 1)
獲取了parent dstream的rdd實例,然後以mapFun爲參數調用 .map(mapFunc)
方法,將得到的新 RDD
實例返回.
(3)對於inputstream又是如何的?
可以看到生成的是BlockRdd.
這樣串起來了,inputstream生成BlockRdd,transfermation對RDD轉換,action實現對數據的輸出。
總結:
我們在代碼裏的兩次 print() 操作產生了兩個 ForEachDStream
節點 x
和 y
,兩次
調用 x.generateJob(time)
和 y.generateJob(time)
方法
x
的 parentDStream.getOrCompute(time)
, d.getOrCompute(time)
; d.getOrCompute(time)
會牽扯 c.getOrCompute(time)
,乃至 a.getOrCompute(time)
, b.getOrCompute(time)
y
節點生成 Job 的過程,與 x
節點的過程非常類似,只是在 b.getOrCompute(time)
時,會命中 get(time)
而不需要觸發 compute(time)
了,這是因爲該 RDD
實例已經在 x
節點的生成過程中被實例化過一次,所以在這裏只需要取出來用就可以了。
整個鏈條就串起來了!