概要
学习过flink的同学应该都知道ExecutionGraph是由JobGraph转换得来的
ExecutionGraph其实就是JobGraph的并行化版本
那Flink底层到底是怎么做的呢?我们今天来看一下。
注:JobGraph的生成原理前面的文章讲过
这张图是我从网上找来的,Flink1.19版本中ExecutionGraph的ExecutionEdge已经被移除,改为了EdgeManager,也就是说IngermediateResult和ExecutionJobVertex之间没有了很多个ExecutionEdge,取而代之的是只有一个的EdgeManager
Flink任务代码
这是一个我准备的Flink任务代码
package org.example.demo;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
public class SocketWordCountDemo {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<String> socketTextStream = env.fromData("data");
SingleOutputStreamOperator<String> mapStream = socketTextStream.map(String::toLowerCase).setParallelism(5);
SingleOutputStreamOperator<Tuple2<String, Integer>> flatMapStream = mapStream.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
out.collect(Tuple2.of(value, 1));
}
}).setParallelism(5);
KeyedStream<Tuple2<String, Integer>, String> keyedStream = flatMapStream.keyBy(x -> x.f0);
SingleOutputStreamOperator<Tuple2<String, Integer>> resultStream = keyedStream.sum(1).setParallelism(5);
resultStream.print("result:").setParallelism(5);
env.execute();
}
}
整体架构流程
1.首先我们进入这个方法createAndRestoreExecutionGraph()
2.可以看到用到了工厂累executionGraphFactory的createAndRestoreExecutionGraph()方法,我们可以看到入参中有JobGraph对象,我们点进这个方法
3.进入buildGraph()方法
4.这个方法代码比较多,我们继续往下看
5.继续往下看
6.进入attachJobGraph()方法,该方法中进行了ExecutionGraph结构的构建
7.attachJobVertices()这个方法就构建了ExecutionJobVertex,这个和JobGraph中的JobVertex一一对应
initializeJobVertices()方法则创建了ExecutionVertex,IntermediateResultPartition和EdgeManager
进入initializeJobVertices()方法
8.遍历每一个JobGraph的jobVertex,基于它创建executionVertex等等
进入initializeJobVertex()方法
9.继续往里点,initializeJobVertex()方法
10.两个重要方法
initialize()方法:创建了ExecutionVertex和IntermediateResultPartition
connectToPreDecessors()方法:创建了EdgeManager
这两个方法我就不点进去看了,因为讲起来也比较麻烦,但其实也并不复杂,如果有兴趣的可以自己点进去看一看
11.回退回去,可以看到这两行代码
第一行,我们可以看到,入参是this,就是我们刚刚构建的ExecutionGraph对象,将其转换为一个拓扑结构图,并封装为ExecutionGraph对象的一个属性,这是真正用来执行的
第二行是执行策略相关的
到这里其实整个ExecutionGraph也就创建的差不多了
小结
ExecutionGraph的生成,如果从整体上来看
Transformations->StreamGraph->JobGraph->ExecutionGraph
前面两步是在客户端执行的
而最后一步是在服务器集群执行生成的