参考
https://juejin.cn/post/6861119250241683464
https://juejin.cn/post/6861119250241683464
Flink简介
Apache Flink是一个框架和分布式处理引擎,用于对无边界和有边界的数据流进行有状态的计算。(unbounded and bounded data streams)
有界流和无界流(unbounded and bounded data streams)
Flink中计算的数据都是流,离线数据就是有界的流,实时数据就是无界流。
无界流: 无界流有一个起点,但没有定义的终点。它们不会终止并在生成数据时提供数据。无限制的流必须被连续处理,即,事件被获取必须立即处理。
无法等待所有输入数据到达,因为输入是无界的,并且在任何时间点都不会完成。处理无限制的数据通常要求以特定顺序(例如事件发生的顺序)提取事件,以便能够推断出结果的完整性。
有界流:有界流具有定义的开始和结束。可以通过在执行任何计算之前提取所有数据来处理有界流。由于有界数据集始终可以排序,因此不需要有序摄取即可处理有界流。有界流的处理也称为批处理。
**Apache Flink擅长处理无边界和有边界的数据集。**对时间和状态的精确控制使Flink的运行时能够在无限制的流上运行任何类型的应用程序。有界流由专门为固定大小的数据集设计的算法和数据结构在内部进行处理,从而产生出色的性能。
Flink核心架构
Flink 采用分层的架构设计,从而保证各层在功能和职责上的清晰。如下图所示,由上而下分别是 API & Libraries 层、Runtime 核心层以及物理部署层:
API & Libraries 层
这一层主要提供了编程 API 和 顶层类库:
编程 API : 用于进行流处理的 DataStream API 和用于进行批处理的 DataSet API;
顶层类库:包括用于复杂事件处理的 CEP 库;用于结构化数据查询的 SQL & Table 库,以及基于批处理的机器学习库 FlinkML 和 图形处理库 Gelly。
Runtime 核心层
这一层是 Flink 分布式计算框架的核心实现层,包括作业转换,任务调度,资源分配,任务执行等功能,基于这一层的实现,可以在流式引擎下同时运行流处理程序和批处理程序。
物理部署层
Flink 的物理部署层,用于支持在不同平台上部署运行 Flink 应用。
Flink 分层 API
在上面介绍的 API & Libraries 这一层,Flink 又进行了更为具体的划分。具体如下:
按照如上的层次结构,API 的一致性由下至上依次递增,接口的表现能力由下至上依次递减,各层的核心功能如下:
SQL & Table API
SQL & Table API 同时适用于批处理和流处理,这意味着你可以对有界数据流和无界数据流以相同的语义进行查询,并产生相同的结果。除了基本查询外, 它还支持自定义的标量函数,聚合函数以及表值函数,可以满足多样化的查询需求。
DataStream & DataSet API
DataStream & DataSet API 是 Flink 数据处理的核心 API,支持使用 Java 语言或 Scala 语言进行调用,提供了数据读取,数据转换和数据输出等一系列常用操作的封装。
Stateful Stream Processing
Stateful Stream Processing 是最低级别的抽象,它通过 Process Function 函数内嵌到 DataStream API 中。 Process Function 是 Flink 提供的最底层 API,具有最大的灵活性,允许开发者对于时间和状态进行细粒度的控制。
Flink 集群架构
按照上面的介绍,Flink 核心架构的第二层是 Runtime 层, 该层采用标准的 Master - Slave 结构, 其中,JobManager是主,TaskManager是从,JobManager其实是一个统称,又包含了三个核心组件:Dispatcher、ResourceManager 和JobMaster,而 Slave 则主要是 TaskManager 进程。
JobMaster:
JobMaster:JobMaster主要负责Job的调度运行、Checkpoint/Savepoint的触发、故障恢复等。每个Job都有一个自己的JobMaster。
这里JobManager和JobMaster可能容易混淆,在早期版本,很多地方(包括官方文档)把JobMaster也称为JobManager,所以如果看一些旧的文档,一定要注意说的JobManager是指广义的JobManager(即包含ResourceManager、JobMaster、Dispatcher)还是狭义的JobManager(即只指JobMaster)。甚至有些时期的文档把广义的JobManager称为JobMaster,把JobMaster称为JobManager。
注意区分“任务”这个词指的是Job还是组成Job的Task,在 Flink 集群架构这一小节中的任务基本都指的是Job。
ResourceManager
ResourceManager:如其名,就是做资源管理的。Flink里面资源是以TaskManager提供的Slot形式存在的,所以其实就是管理Slot的。TaskManager启动后会向ResourceManager报告自己的slot情况,并且通过心跳和通知机制定期更新。之所以把这个模块单独出来,是因为资源管理框架已经很多了(但功能、实现、使用又有差异),比如YARN、Mesos、Kubernetes。所以单独出来以后,方便分别实现支持不同框架的ResourceManager 。
另外,ResourceManager在设计上:
1)是无状态的,因为它的数据都是别人主动报告给它的,所以重启后可以重新获取。不过有的实现可能会有一点状态。
2)故障后不影响已经在运行的任务。ResourceManager一个集群只有一个。
Dispatcher
Dispatcher:负责接收客户端提交的执行程序,并传递给 JobMaster ,之后将任务交给JobMaster去调度管理。除此之外,它还提供了一个 WEB UI 界面,用于监控作业的执行情况。不考虑standby的情况下,Dispatcher一个集群只有一个。
TaskManager
- Flink集群中,真正干活的工作进程,Flink集群中有多个TaskManager,每个 TaskManager都包含了一定数量的插槽(slots)。
- 启动之后,TaskManager会向ResourceManager注册它使用的插槽;收到ResourceManager的指令后,TaskManager会将一个或多个插槽提供给JobMaster调用。JobMaster就可以向slot分配tasks(tasks不是job)
- 执行过程中,一个TaskManager可以跟其它运行同一应用程序的TaskManager交换数据
提交作业
所以,一个flink任务提交流程就是图中所示的8步:
- 用户通过Client(比如命令行 flink run和Web UI)提交任务到Dispatcher;
- Dispatcher为该任务创建JobMaster,并移交Job;
- JobMaster向ResourceManager申请资源(即Slot);
- 此时如果没有资源,并且ResourceManager有动态创建TaskManager的能力(有的部署方式有,有的部署方式没有),ResourceManager就会创建TaskManager;没有动态创建TaskManager能力的部署方式,则需要先部署好TaskManager;
- TaskManager创建好之后,向ResourceManager注册自己的资源;
- ResourceManager会发出命令提供给TaskManager相关资源(slot)
- ResourceManager分配资源后,该资源的所有者TaskManager就会向JobMaster提供可用的slot供JobMaster调用。
- 提交在slot中执行的 SubTask,这里的SubTask指的是A subtask is one parallel slice of a task,即一个 Task 可以按照其并行度拆分为多个 SubTask