Flink Runtime
Flink Runtime
1、Flink整体架构
针对不同的环境,提供不同的API,用来编写流作业与批作业的DataStream和DataSet,并对多种API提供统一的分布式作业执行引擎,也就是RunTime层,Flink可以运行在多种不同的环境中,本地、Yarn或者云等
2、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会从缓存的请求中选择相应的请求并结束相应的请求过程。
当 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 开始继续执行。
4.2 Restart-individual
适用于 Task 之间没有数据传输的情况。这种情况下,我们可以直接重启出错的任务。
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,