1.Flink各级调度核心原理概述
Flink是Apache软件基金会下开源的分布式流批一体计算框架,具备实时流计算和高吞吐批处理计算的大数据计算能力。本专栏内容为Flink源码解析的记录与分享,本文先总体结合源码介绍Flink各级调度的核心原理和调度过程,本专栏后续文章再继续依次展开Flink每级调度的完整源码解析。
本文解析的Flink源码版本为:flink-1.19.0
2.Flink on Yarn的计算调度与任务执行完整流程
本文解析的Flink计算调度与任务执行是基于Yarn架构的,依次完成对Flink程序进行Transformation、StreamGraph、JobGraph、ExecutionGraph、物理执行图等多级计算拓扑构建与任务划分,并为每个划分好的Task分配计算资源,最终把Task分布式地执行在各TaskManager节点中。
Flink程序在Yarn集群执行主要包括以下组件:
CliFrontend:Flink客户端,负责进行Transformation、StreamGraph、JobGraph生成,并最终将JobGraph、Jar包及依赖向集群提交。
Dispatcher:Flink Application Master的接收组件,负责接收CliFrontend发送的JobGraph,下载jar与依赖,最终启动JobMaster为本次提交的Flink程序进行任务调度。
JobMaster:Flink Application Master的任务管理与调度组件,负责ExecutionGraph生成、SchedulingPipelinedRegion划分与调度,为Task向ResourceManager申请Slot资源,并最终把Task提交到被分配Slot的TaskManager。
Flink Resource Manager:Flink Application Master资源管理组件,负责向Yarn集群的Resource Manager申请Container资源并启动TaskManager,为Flink程序分配Slot。
TaskManager:Flink程序的执行端,负责在Resource Manager分配的Slot上创建并执行分布式Task任务。
Flink程序在Yarn上的执行完整流程的具体步骤如下:

Flink客户端部分:
1.命令启动:Flink run命令启动Flink的CliFrontend客户端。
2.环境准备:CliFrontend解析提交参数、生成配置与上下文环境、执行Flink的主程序。
3.Transformation转换:Flink主程序把DataStreamAPI转换成Transformation集合。
4.StreamGraph生成:CliFrontend通过StreamGraphGenerator生成StreamGraph。
5.JobGraph生成:CliFrontend通过StreamingJobGraphGenerator生成JobGraph。
6.提交集群:CliFrontend通过ClusterClient向HDFS上传JobGraph、Jar、Artifacts,向Yarn集群提交Request。
注:在Yarn部署模式中Pre Job于Session是Flink主程序是通过CliFrontend客户端启动,在Application则客户端部分运行在Yarn Application Master中的YarnApplicationClusterEntryPoint,此外,Application模式中Jar和Artifacts已存在HDFS中,无需在客户端上传。
Flink集群部分:
7.Dispatcher作业接收:Dispatcher解析Request,从HDFS下载JobGraph、jar、artifacts,创建JobMaster处理JobGraph。
8.ExecutionGraph生成:JobMaster通过JobGraph生成ExecutionGraph。
9.SchedulingPipelinedRegion划分与调度:JobMaster把ExecutionGraph划分为SchedulingPipelinedRegion,并为SchedulingPipelinedRegion的每个Execution依次申请Slot。
10.ResourceManager分配Slot:Flink ResourceManager的SlotManager为Task分配Slot。
11.TaskManager资源申请与启动:若当前资源不足以分配Slot,Flink ResourceManager向Yarn Resource Manager申请Container启动新的TaskManager。
12.向TaskManager提交Task:JobMaster把SchedulingPipelinedRegion中每个Execution封装为TaskDeploymentDescriptor,向TaskManger提交Task。
13.Task执行:TaskManager创建Task、StreamTask算子链、InputGate和ResultParitition,并最终执行Task。
其中Yarn有三种部署模式:Pre Job、Session和Application模式,区别在各Flink程序在Session模式下是共用Yarn中的Flink集群组件资源,而Pre Job与Application模式会为每个Flink程序单独在Yarn上启动一套Flink集群资源。此外,Yarn Application把原本Client上CliFrontend功能放在了Yarn Flink Application Master中。Flink在Yarn上的三种部署模式存在组件启动上的差异,但在Flink计算调度与任务执行的核心流程是一致。
3.Flink主类-DataStream数据流转换为Transformation集合
Flink程序的起点为用户使用flink run命令启动Flink CliFrontend客户端。CliFrontend客户端会在解析提交参数、生成程序的配置与上下文后环境后,执行Flink主类的main()方法进入Flink主类的业务逻辑。Flink主类是研发人员通过Flink API编写的DataStream代码及Flink执行环境、状态管理、Checkpoint等环境与配置代码。下面从Flink主类的main()方法开始解析。
执行主类main()方法本质是把在代码中编写的DataStream数据流转换为Transformation集合:

以Map为例,Flink程序在执行时会调用DataStream.map()方法,该方法会把DataStream的map算子转换为OneInputTransformation,把map操作封装在StreamMap中的MapFunction中。
首先Flink会创建StreamMap(StreamOperator的具体实现)封装用户定义的MapFunction与数据处理逻辑,再通过创建SimpleOperatorFactory封装StreamMap,最终创建Transformation封装SimpleOperatorFactory、并行度信息parallelism、输出类型outputType和上游Transformation的引用。

DataStream数据流转换Transformation集合的具体步骤如下:
1.创建StreamOperator封装算子逻辑:示例以Map为例,DataStream的map()函数会创建StreamMap(StreamOperator的具体实现),StreamMap中又封装了MapFunction。
2.创建SimpleOperatorFactory:Flink又继续创建了SimpleOperatorFactory封装StreamMap。
3.将DataStream转变为Transformation:创建Map对应的Transformation (具体为OneInputTransformation) ,Transformation内封装了对上游Transformation的引用、SimpleOperatorFory、并行度、输出类型等算子信息。
4.将Transformation加入StreamExecutionEnvironment:将Transformation加入StreamExecutionEnvironment中的List<Transformation> ,完成单个算子从DataStream数据流到 Transformation List集合的转换。
5.最终完成DataStream到Transformation的转化:依次将main()方法所有DataStream转换为Transfromation,最终形成StreamExecutionEnvironment的List<Transformation>。
DataStream数据流转换为Transformation集合源码图解:

DataStream数据流向Transformation集合转换的关键步骤是依次执行DataStream的所有算子API,将DataStream算子转换为Transformation,并把用户数据处理逻辑封装在StreamOperator中,以下为DataStream数据流向Transformation集合转换关键步骤的源码解析,以Map算子为例:
StreamMap(StreamOperator的实现)创建源码 (DataStream.map()方法):
//创建StreamOperator,并继续进行transform生成
transform("Map", outputType, new StreamMap<>(clean(mapper)));
//注: 1.mapper为用户定义的MapFunction<T, R>函数
// 2.clean()方法作用为精简函数冗余依赖
SimpleOperatorFactory创建源码 (DataStream.transform()方法):
//创建SimpleOperatorFactory封装StreamOperator
doTransform(operatorName, outTypeInfo, SimpleOperatorFactory.of(operator));
//其中operator为StreamOperator(本示例为:StreamMap)
Transformation创建源码 (DataStream.doTransform()方法):
//Transformation创建,以OneInputTransformation为例
OneInputTransformation<T, R> resultTransform =
new OneInputTransformation<>(
this.transformation,
operatorName,
operatorFactory,
outTypeInfo,
environment.getParallelism(),
false);
@SuppressWarnings({"unchecked", "rawtypes"})
SingleOutputStreamOperator<R> returnStream =
new SingleOutputStreamOperator(environment, resultTransform);
//向StreamExecutionEnvironment添加Transform
getExecutionEnvironment().addOperator(resultTransform);
4.StreamGraph生成
完成DataStream数据流向Transformation集合转换后,Flink开始进行StreamGraph生成。
StreamGraph生成的本质是遍历Transformation集合,把Transformation集合转换为由StreamNode与StreamEdge组成的StreamGraph图。

Flink的StreamGraph生成主要是通过遍历Stream

1040

被折叠的 条评论
为什么被折叠?



