DStreamGraph
WebBlog2《深入Streaming中的数据抽象DStream》中的Transformation DStream部分提到过:parent.getOrCompute依据DStream之间的依赖关系,将对DStream的操作都转换成对RDD的操作,这样DSream的依赖关系也与RDD之间依赖关系同时建立了起来。也就是说:应该首先将计算逻辑描述为RDD DAG的“模板”,即DStreamGraph,在后面Job动态生成的时候,针对每个batch,Streaming都将根据DStreamGraph生成一个RDD DAG的实例。那么DStreamGraph内部是如何记录DStream之间的依赖关系呢?
1.反向记录依赖,因为RDD 的计算是被触发了以后才进行 lazy 求值的。
2.new一个d的一个下游ForEachDstream x ,每个batch动态生成RDD实例时:以 x 为根节点、进行一次 BFS,就可快速得到需要进行实际计算的最小集合,比如{a, b, c, d}。不能被遍历到的DStream节点,g和h不属于物理的DStreamGraph,在实际运行过程中不产生任何作用。
3. DStreamGraph记录了到所有的Output DStream节点的引用,同时也记录了时常需要遍历没有上游依赖的Input DStream节点,记录一下就可以避免每次为查找 Input DStream而对Output DStream进行BFS的消耗。
JobScheduler
总体负责动态作业调度的具体类是JobScheduler,有两个非常重要的成员:JobGenerator和ReceiverTracker。JobScheduler将每个batch的RDD具体生成工作委托给JobGenerator,而将源头输入数据的记录委托给 ReceiverTracker。
每次 RDD DAG生成包含 5 个步骤:
1.要求ReceiverTracker将目前已收到的数据进行一次allocate,即将上次batch 切分后的数据切分到到本次新的batch里。
2.要求DStreamGraph复制出一套新的RDD DAG的实例(从尾节点开始遍历)
3.获取第1步ReceiverTracker分配到本batch的源头数据的meta信息;
4.将第2步生成的本batch的RDD DAG,和第 3 步获取到的meta信息,一同提交给JobScheduler异步执行;
5.只要提交结束,就马上对整个系统的当前运行状态做一个checkpoint。