首页 > > > Flink源码解析-从API到JobGraph
通常情况下,如果想要使用flink进行并行计算,开发者会把自己的业务逻辑抽象成流式计算的模型,使用flink提供的api定义Job来实现该模型,因此一个flinkjob的生命是从api开始的。我们从一个官网的word count的例子开始,稍做一些修改,代码如下:

首先,代码段1获取一个类StreamExecutionEnvironment的对象,我们稍后会详细介绍这个类;代码段2~7便是利用streamming Api来定义自己的Job,方法:
addSource( ... ),flatMap( ... ), keyBy(),
timeWindow( ... ), sum( ... ), print( ... )就是flink提供的API;代码段7是提交上面定义的job 。
StreamExecutionEnvironment, API, transformation
我们来看一下类:StreamExecutionEnvironment,有下面一个属性:
protected final List<StreamTransformation<?>> transformations = new ArrayList<>();
有以下几点需要指出:

StreamGraph是flink客户端把用户定义的Transformation(就是存储在里面的那个ArrayList< StreamTransformation>)组织成StreamGraph——逻辑上的DAG。代码段:
env.execute("word count on flink");做了两件事情:
此部分我们先来讨论1,首先Flink到底有多少类型的transformation呢?如下图:

Flink Client会遍历StreamExecutionEnvironment中的transformations数组,按照用户定义构建上面的DAG图。其中:
StreamNode对象里面存储了用户的udf对象、输入输出的序列化方法、所有输入和输出的StreamAdge对象、该StreamNode对应的transformationID等信息。
StreamAdge对象存储了上游的StreamNode、下游的StreamNode还有自身的一个edgeId。
上文提到过,StreamGraph会被切分成JobGraph,这里来介绍一下:首先,StreamGraph和JobGraph有什么区别,StreamGraph是逻辑上的DAG图,不需要关心jobManager怎样去调度每个Operator的调度和执行;JobGraph是对StreamGraph进行切分,因为有些节点可以打包放在一起被JobManage安排调度,因此JobGraph的DAG每一个顶点就是JobManger的一个调度单位。假如StreamGraph切分如下图:


当然其他条件也非常重要,但是在本文,暂不展开。这里我们来着重介绍一下第一条规则:下游的StreamNode的输入StreamAdge的个数必须是1。根据这条规则我们至少可以得到下面两条结论:
至此Flink客户端的工作基本完成,接下来Flink客户的通过Akka把生成的JobGraph提交给JobManager,JobManager开始根据JobGraph部署工作,接下来详细介绍下改过程。
上文提到,在客户的完成JobGraph的构建之后,将其通过akka提交给JobManager,接下来我们介绍下JobManager怎样按照JobGraph的规划进行任务调度。
JobManager收到客户端提交的JobGraph之后,会构建ExecutionGraph;ExecutionGraph的拓扑结构和JobGraph保持一致,只是把JobGraph重构成ExecutionJobGraph,其中按照JobVertex将顶点分装成ExecutionJobVertex,按照JobEdge将边封装成ExecutionAdge,还构建IntermediateResult(中间数据)用来描述节点之间的Data shuffle 。如下图:

上游节点会把产生的数据写到IntermediateReslut(下文称:中间数据集)中,是中间数据集的生产者;下游节点会处理中间数据集产生的数据,是中间数据集的消费者,具体的可能有下面两种情况:

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69918097/viewspace-3159181/ ,如需转载,请注明出处,否则将追究法律责任。