摘要: 鸟瞰 Flink 架构,分析 Flink 内部组件工作机制。
Flink 架构图
一个完整的 Flink 集群由一个 Jobmanager 和若干个 Taskmanager 组成,Jobmanager 主要负责调度 task 以及 协调 Checkpoint。Taskmanager 则负责具体的 task 执行,以及数据流的交换。
可以通过多种方式启动 JobManager 和 TaskManager:直接在机器上作为standalone 集群启动、在容器中启动、或者通过YARN等资源框架管理并启动。TaskManager 连接到 JobManagers,宣布自己可用,并被分配工作。
提交作业流程
以一个作业提交的流程来说明 Flink 各个组件是如何交互和工作的:
Flink 集群模式
Flink 集群类型一般有以下几种:
-
Flink Session 集群
这种模式下,集群自创建开始,最后到集群生命周期结束,不受作业因素影响; 集群下的多个作业共享 内存、网络、磁盘等资源,如果集群出现异常,该集群下的所有作业都会收到影响。
优点:提交作业速度很快,无需提前申请资源; 并且资源利用率较高。
缺点:作业之间隔离性较差,横向扩展不太方便。
-
Flink job 集群
这种模式也称 pre-job 模式,集群交由 资源管理器托管,例如 Yarn ,需要运行作业,第一步申请资源,启动一个 Flink 集群,第二步提交作业,这种模式下,每个作业会独享一个 Flink 集群。
优点:作业之间相互隔离,稳定性高,并且不同作业可以根据资源情况灵活调整。
缺点:资源浪费,并且作业启动较慢。
-
Flink Application 集群
这种模式也称 Application 模式,这种模式的集群和作业相关,每一个作业独享一个集群,无需事先启动一个集群,而且直接从作业 jar 中提取 JobGraph 执行。这种模式下,每一个作业就是一个 Application ,同时也是一个 Flink 集群。
优点:集群直接相互隔离,可以很好地利用资源;
缺点:暂无。
JobManager
在 Flink 集群中,JobManager 负责协调、调度 Task ,以及作业快照、从快照中恢复等功能。
Jobmanager 核心组件:
-
ResourceManager
ResourceManager 负责 Flink 集群中的资源分配、回收,并管理 task slot。
-
Dispatcher
Dispatcher 提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。
-
JobMaster
JobMaster 负责管理单个JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster。
一个 Flink 集群中,至少有一个 Jobmanager ,可以设定多个 Jobmanager ,leader 只有一个,其他 Jobmanager 为 standby。
Taskmanager
Taskmanager 负责具体 task 的执行,以及数据流的交换。 同时, Taskmanager 需要将资源状态向 Jobmanager 汇报。
算子链
假设 Flink 算子并行度为2,该算子的 subTask 有两个,Flink 会将算子的 subtasks 链接成 tasks。每个 tasks 由一个线程执行。将算子链接成 task 是个有用的优化:它减少线程间切换、缓冲的开销,并且减少延迟的同时增加整体吞吐量,此时一个线程将会执行多个 subTask。
链行为是可以配置的,如果想对整个作业禁用算子链,可以调用 StreamExecutionEnvironment.disableOperatorChaining()
。
Slot
task slot 代表 Taskmanager 中的可用资源(不包括CPU)的集合,例如,如果一个 Taskmanager 有3个 slot,那每个 slot 将会平分 Taskmanager 的内存资源,当第四个 task 提交过来时,task 将进入 SCHEDULE 状态,需要等待其他 task 执行完成,才能执行下一个 task。
slot共享:
默认情况下,Flink 允许 subtask 共享 slot,即便它们是不同的 task 的 subtask,只要是来自于同一作业即可。算子最大并行度和 slot 数量一致,算子之间的数据交换会根据不同的策略进行。
每一个 subtasks 算子链由一个线程执行,在 slot 中的执行情况如下:
task 数据交换策略
数据交换策略定义了在物理执行流图中如何将数据分配给任务,
-
Forward
将数据从一个任务发送到接收任务。如果两个任务都位于同一台物理计算机上(这通常由任务调度器确保),这种交换策略可以避免网络通信。
-
BroadCast
将所有数据发送到算子的所有的并行任务上面去。因为这种策略会复制数据和涉及网络通信,所以代价相当昂贵。
-
Key-based
基于键控的策略通过Key值(键)对数据进行分区保证具有相同Key的数据将由同一任务处理。
-
Random
随机策略统一将数据分配到算子的任务中去,以便均匀地将负载分配到不同的计算任务。
参考:
https://nightlies.apache.org/flink/flink-docs-release-1.14/zh/docs/concepts/flink-architecture/