Flink Runtime

Flink Runtime

1、Flink整体架构

Flink Runtime
​ 针对不同的环境,提供不同的API,用来编写流作业与批作业的DataStream和DataSet,并对多种API提供统一的分布式作业执行引擎,也就是RunTime层,Flink可以运行在多种不同的环境中,本地、Yarn或者云等

2、Runtime层

Flink Runtime
​ Master部分包含了三个组件,Dispatcher,ResourceManager,JobManager。Dispatcher负责接收Client提交的Job,并负责启动一个JobManager对象,在整个Flink集群只有一个ResourceManager(是不YARN),负责资源的管理,JobManager负责作业的执行,每个作业都有自己的 JobManager。这三个组件都包含在AM进程中。

​ 在作业提交的时候,首先启动Client进程负责作业的编译与提交,将用户编写的代码编译成一个JobGraph,进行一些优化,并提交到集群中,Session模式的AM会提前启动,Per-Job模式不会提前启动,Client需要向Yarn去申请,然后将作业提交到AM的Dispatcher 。

​ 当作业到Dispatcher的时候,首先会拉起一个JobManager,JobManager在向ResourceManager申请资源来启动作业中具体的任务,这时根据Session和Per-Job模式区别是否进行上图中的6、7步过程,RM选择空闲的资源进行分配,并通知TaskManager相应的TM分配资源给JobManager,TaskManager向JobManager进行注册,JobManager收到注册的Solt,实际进行Task的提交

​ TaskManager 收到 JobManager 提交的 Task 之后,会启动一个新的线程来执行该 Task。Task 启动后就会开始进行预先指定的计算,并通过数据 Shuffle 模块互相交换数据。

3、资源管理与作业调度

​ 作业调度的基础是对资源的管理,首先作业调度可以看成资源和任务的比配过程,在Flink中资源是通过Slot表示,在ResouceManager中,有一个叫做SlotManager的组件,维护者所有TaskManager的Slot信息,在JobManager申请Slot的时候,根据Session或者Per-Job模式去选取Slot或者申请资源启动TaskManager,并注册后在选取Slot,通过RPC请求告诉相应的Task Executor分配Slot给JobManager,如果是第一次, 首先建立连接,发送提供Slot的RPC请求,在JobManager中,所有的Task缓存到SlotPool中,SlotPool会从缓存的请求中选择相应的请求并结束相应的请求过程。

Flink Runtime

​ 当 Task 结束之后,无论是正常结束还是异常结束,都会通知 JobManager 相应的结束状态,然后在 TaskManager 端将 Slot 标记为已占用但未执行任务的状态。JobManager 会首先将相应的 Slot 缓存到 SlotPool 中,但不会立即释放。这种方式避免了如果将 Slot 直接还给 ResourceManager,在任务异常结束之后需要重启时,需要立刻重新申请 Slot 的问题。

​ SlotPool 中缓存的 Slot 超过指定的时间仍未使用时,SlotPool 就会发起释放该 Slot 的过程。与申请 Slot 的过程对应,SlotPool 会首先通知 TaskManager 来释放该 Slot,然后 TaskManager 通知 ResourceManager 该 Slot 已经被释放,从而最终完成释放的逻辑。

4、错误恢复

4.1 Restart-all

​ 直接重启所有的 Task。对于 Flink 的流任务,由于 Flink 提供了 Checkpoint 机制,因此当任务重启后可以直接从上次的 Checkpoint 开始继续执行。

Flink Runtime

4.2 Restart-individual

​ 适用于 Task 之间没有数据传输的情况。这种情况下,我们可以直接重启出错的任务。

Flink Runtime

4.3 Failover策略

​ Flink 的批作业没有 Checkpoint 机制,因此对于需要数据传输的作业,直接重启所有 Task 会导致作业从头计算,从而导致一定的性能问题。

​ 在一个 Flink 的 Batch 作业中 Task 之间存在两种数据传输方式,一种是 Pipeline 类型的方式,这种方式上下游 Task 之间直接通过网络传输数据,因此需要上下游同时运行;另外一种是 Blocking 类型,这种方式下,上游的 Task 会首先将数据进行缓存,因此上下游的 Task 可以单独执行。基于这两种类型的传输,Flink 将 JobGraph 中使用 Pipeline 方式传输数据的 Task 的子图叫做 Region,从而将整个 ExecutionGraph 划分为多个子图,自己觉得比较像Spark中的宽依赖,也就是Shuffle,

tionGraph 划分为多个子图,自己觉得比较像Spark中的宽依赖,也就是Shuffle,

Flink Runtime