SparkStreaming从入门到放弃(三)

本文主要讲解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生成BlockRddtransfermationRDD转换,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 节点的生成过程中被实例化过一次,所以在这里只需要取出来用就可以

整个链条就串起来了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章