Flink 架构
一、Flink 集群剖析
Flink 运行时由两种类型的进程组成:一个 JobManager 和多个 TaskManager
1.1 JobManager
JobManager 具有许多与协调 Flink 应用程序的分布式执行有关的职责:它决定何时调度下一个 task(或一组 task)、对完成的 task 或执行失败做出反应、协调 checkpoing、并且协调从失败中恢复等。这个进程由三个不同的组件组成:
-
ResourceManager
ResourceManager 负责 Flink 集群中的资源提供、回收、分配,它管理task slots(Flink 集群中资源调度的单位)。Flink 为不同的环境和资源提供者实现了对应的 ResourceManager。在 standalone 设置中,ResourceManager 只能分配可用 TaskManager 的 slots,而不能自行启动新的 TaskManager。
-
Dispatcher
Dispatcher 提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。
-
JobMaster
JobMaster 负责管理单个 JobGraph 的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster。
1.2 TaskManager
TaskManager(也成为 worker)执行作业流的 task,并且缓存和交换数据流。
必须始终至少有一个 TaskManager。在 TaskManager 中资源调度的最小单位是 task slot。TaskManager 中 task slot 的数量表示并发处理 task 的数量。一个 task slot 中可以执行多个算子。
二、Tasks 和算子链
task 是指物理执行图中的节点,subtask 是指负责数据流 Partition 的 task。
对于分布式执行,Flink 将算子的 subtasks 链接成 tasks。每个 task 由一个线程执行。将算子链接成 task 由如下优点:
1. 减少线程间切换、缓冲的开销
2. 减少延迟的同时增加整体吞吐量
每个 subtask 由一个线程执行,把算子合并到一个 subtask 需要满足的条件:相同并行度的 one-to-one 操作,并且在同一个slot共享组。
三、Task Slots 和资源
3.1 slot 的概念及作用
每个 worker(TaskManager)都是一个 JVM 进程,可以在单独的线程中执行一个或多个 subtask。为了控制一个 TaskManager 中接受多少个 task,就有了所谓的 task slots(至少一个)。
每个 task slot 代表 TaskManager 中资源的固定子集(静态的概念)。通过 slot 可以实现内存隔离(目前没有 CPU 隔离)。
具有多个 slot 意味着更多 subtask 共享同一 JVM。同一 JVM 中的 task 共享 TCP 链接(通过多路复用)和心跳信息。它们还可以共享数据集和数据结构,从而减少了每个 task 的开销。
3.2 slot 共享
Flink 允许 subtask 共享 slot,即便它们是不同的 task 的 subtask,只要是来自于同一作业即可。结果就是一个 slot 可以持有整个作业管道。允许 slot 共享有以下主要优点:
- Flink 集群所需的 task slot 和作业中使用的最大并行度(算子并行度的最大值)恰好一样。无需计算程序总共包含多少个 task
- 可以有管道挂掉
- 合理利用资源,防止闲置。如果没有 slot 共享,非密集 subtask(source/map())将阻塞和密集型 subtask(window) 一样多的资源。通过 slot 共享,我们示例中的基本并行度从 2 增加到 6,可以充分利用分配的资源,同时确保繁重的 subtask 在 TaskManager 之间公平分配。