Flink 四层转化流程【Program、StreamGraph、JobGraph、ExecutionGraph、物理执行计划】

目录

Flink 四层转化流程

Program 到 StreamGraph 的转化

StreamGraph 到 JobGraph 的转化

JobGraph 到 ExexcutionGraph 以及物理执行计划


Flink Job 执行作业的流程,文章将从两个方面进行分享:一是如何从 Program 到物理执行计划,二是生成物理执行计划后该如何调度和执行

Flink 四层转化流程

Flink有四层转换流程,第一层为 Program到 StreamGraph第二层为 StreamGraph到 JobGraph第三层为 JobGraph到ExecutionGraph第四层为 ExecutionGraph到物理执行计划。通过对 Program的执行,能够生成一个DAG执行图,即逻辑执行图。如下:

第一层 StreamGraph Source 节点开始,每一次 transform 生成一个 StreamNode, 两个 StreamNode通过 StreamEdge连 接在一起,形成 StreamNode和 StreamEdge构成的 DAG。
第二层 JobGraph,依旧从 Source 节点开始,然后去遍历寻找能够嵌到一起的 operator,如果能够嵌到一起则嵌到一起,不能嵌到一起的单独生成 jobVertex,通过 JobEdge 链接上下游 JobVertex,最终形成 JobVertex 层面的 DAG。
第三层 JobVertex DAG 提交到任务以后,从 Source 节点开始排序 , 根据 JobVertex 生成 ExecutionJobVertex, 根据 jobVertex 的 IntermediateDataSet 构建 IntermediateResult,然后 IntermediateResult 构建上下游的依赖关系,形成 ExecutionJobVertex 层面的 DAG 即 ExecutionGraph。
最后通过 ExecutionGraph 层到物理执行层。

Program 到 StreamGraph 的转化

Program 转换成 StreamGraph 具体分为三步:
【1】从StreamExecutionEnvironment.execute开始执行程序,将 transform添加到 StreamExecutionEnvironmenttransformations
【2】调用 StreamGraphGenerator generateInternal 方法,遍历 transformations 构建 StreamNode StreamEage
【3】通过 StreamEdge 连接 StreamNode

通过 WindowWordCount来看代码到 StreamGraph的转化,在 flatMaptransform设置 slot共享组为 flatMapsg,并发设置为4,在聚合的操作中设置 slot共享组为 sumsgsum()counts()并发设置为3,这样设置主要是为了演示后面如何嵌到一起的,跟上下游节点的并发以及上游的共享组有关。

WindowWordCount代码中可以看到,在 readTextFile()中会生成一个transform,且 transform的ID是1;然后到 flatMap()会生成一个transformtransform的ID是2;接着到 keyBy()生成一个 transform的ID是3;再到 sum()生成一个 transformID是4;最后到 print()生成 transform的ID是5

transform 的结构如图所示,第一个是 flatMap transform,第二个是 windowtransform, 第 三 个 是 SinkTransform transform。 除此之外, 还能在 transform 的结构中看到每个 transform 的 input 是什么。接下来介绍一下 StreamNode StreamEdge
【1】StreamNode 是用来描述 operator 的逻辑节点,其关键成员变量有 slotSharingGroupjobVertexClassinEdgesoutEdges 以 及 transformationUID
【2】StreamEdge 是用来描述两个 operator 逻辑的链接边,其关键变量有sourceVertextargetVertex

WindowWordCount transformStreamGraph 转化如图所示,StreamExecutionEnvironment transformations 存在 3 个 transform,分别是 FlatMap(Id 2)、Window(Id 4)、Sink(Id 5)

transform 的时候首先递归处理 transform input,生成 StreamNode,然后通过 StreamEdge 链接上下游 StreamNode。需要注意的是,有些 transform 操作并不会生成StreamNode PartitionTransformtion,而是生成个虚拟节点。

在转换完成后可以看到,streamNodes 有四种 transform 形式,分别为 SourceFlat MapWindowSink

每个 streamNode 对象都携带并发个数slotSharingGroup执行类等运行信息。

StreamGraph 到 JobGraph 的转化


StreamGraph 到 JobGraph 的转化步骤:
【1】设置调度模式,Eager 所有节点立即启动。
【2】广度优先遍历 StreamGraph为每个 streamNode 生成 byte 数组类型的 hash
【3】从 source 节点开始递归寻找嵌到一起的 operator,不能嵌到一起的节点单独生成 jobVertex,能够嵌到一起的开始节点生成 jobVertex,其他节点以序列化的形式写入到 StreamConfig,然后 merge CHAINEDTASKCONFIG,再通过 JobEdge 链接上下游 JobVertex
【3】将每个 JobVertex 的入边 (StreamEdge) 序列化到该 StreamConfig
【4】根据 group name 为每个 JobVertext 指定 SlotSharingGroup
【5】配置 checkpoint
【6】将缓存文件存文件的配置添加到 configuration 中。
【7】设置 ExecutionConfig

从 source 节点递归寻找嵌到一起的 operator 中,嵌到一起需要满足一定的条件,具体条件介绍如下:
【1】下游节点只有一个输入。
【2】下游节点的操作符不为 null。
【3】上游节点的操作符不为 null。
【4】上下游节点在一个槽位共享组内。
【5】下游节点的连接策略是 ALWAYS
【6】上游节点的连接策略是 HEAD 或者 ALWAYS
【7】edge 的分区函数是 ForwardPartitioner 的实例。
【8】上下游节点的并行度相等。
【9】可以进行节点连接操作。

JobGraph 对象结构如上图所示,taskVertices 中只存在 WindowFlat MapSource 三个 TaskVertexSink operator 被嵌到 window operator 中去了。

为什么要为每个 operator 生成 hash 值

Flink 任务失败的时候,各个 operator 是能够从 checkpoint 中恢复到失败之前的状态的,恢复的时候是依据 JobVertexIDhash 值 ) 进行状态恢复的。相同的任务在恢复的时候要求 operator hash 值不变,因此能够获取对应的状态。

每个 operator 是怎样生成 hash 值的

如果用户对节点指定了一个散列值,则基于用户指定的值能够产生一个长度为16 的字节数组。如果用户没有指定,则根据当前节点所处的位置,产生一个散列值
考虑的因素主要有三点:
【1】在当前 StreamNode 之前已经处理过的节点的个数,作为当前 StreamNode 的 id,添加到 hasher 中;
【2】遍历当前 StreamNode输出的每个 StreamEdge,并判断当前 StreamNode 与这个 StreamEdge 的目标 StreamNode 是否可以进行链接,如果可以,则将目标 StreamNode 的 id 也放入 hasher 中,且这个目标 StreamNode 的 id 与当前 StreamNode 的 id 取相同的值
【3】将上述步骤后产生的字节数据,与当前 StreamNode的所有输入 StreamNode 对应的字节数据,进行相应的位操作,最终得到的字节数据,就是当前 StreamNode 对应的长度为 16 的字节数组。

JobGraph 到 ExexcutionGraph 以及物理执行计划

JobGraph 到 ExexcutionGraph 以及物理执行计划的流程:
【1】将 JobGraph 里面的 jobVertex Source 节点开始排序。
【2】在 executionGraph.attachJobGraph(sortedTopology)方法里面,根据 JobVertex 生成 ExecutionJobVertex,在 ExecutionJobVertex 构造方法里面,根据 jobVertex IntermediateDataSet 构建 IntermediateResult,根 据 jobVertex 并 发构建 ExecutionVertexExecutionVertex构建的时候,构建 IntermediateResultPartition
每一个 Execution 构建 IntermediateResult 数个 IntermediateResultPartition );将创建的 ExecutionJobVertex 与前置的 IntermediateResult 连接起来。
【3】构建 ExecutionEdge ,连接到前面的 IntermediateResultPartition,最终从ExecutionGraph 到物理执行计划。

猜你喜欢

转载自blog.csdn.net/zhengzhaoyang122/article/details/107464837
今日推荐