这是我参与「第四届青训营 」笔记创作活动的第5天
Flink 架构
Flink 运行时由两种类型的进程组成:一个 JobManager 和一个或多个 TaskManager。
客户端不是运行时和程序执行的一部分,而是用于准备数据流并将其发送到 JobManager。之后,客户端可以断开连接(分离模式)或保持连接以接收进度报告(附加模式)。客户端作为触发执行的 Java/Scala 程序的一部分运行,或在命令行进程中运行。./bin/flink run ...
JobManager和TaskManagers可以通过多种方式启动:直接在机器上作为独立集群启动,在容器中,或者由YARN等资源框架管理。
JobManager 作业管理者
JobManager 有许多与协调 Flink 应用程序分布式执行相关的职责:它决定何时安排下一个任务(或一组任务),对完成的任务或执行失败做出反应,协调检查点,并协调故障恢复等。此过程由三个不同的组件组成:
-
资源管理器
ResourceManager 负责 Flink 集群中的资源解除/分配和配置 — 它管理任务槽,这些槽是 Flink 集群中资源调度的单位(参见 TaskManagers)。Flink 为不同的环境和资源提供商(如 YARN、Kubernetes 和独立部署)实现了多个 ResourceManagers。在独立设置中,资源管理器只能分配可用任务管理器的插槽,而不能自行启动新的任务管理器。
-
调度
调度程序提供了一个 REST 接口来提交 Flink 应用程序以供执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 以提供有关作业执行的信息。
-
JobMaster
JobMaster负责管理单个JobGraph的执行。多个作业可以在一个 Flink 集群中同时运行,每个作业都有自己的 JobMaster。
始终至少有一个 JobManager。高可用性设置可能具有多个 JobManager,其中一个始终是领导者,其他处于备用状态
TaskManagers 任务管理者
TaskManager(也称为workers)执行数据流的任务,并缓冲和交换数据流。
必须始终至少有一个TaskManager。任务管理者中资源调度的最小单位是任务槽。任务管理者中的任务槽数指示并发处理任务数。
任务和算子链
对于分布式执行,Flink 将运算符子任务一起子任务化为任务。每个任务由一个线程执行。将运算符链接在一起到任务中是一种有用的优化:它减少了线程到线程切换和缓冲的开销,并在减少延迟的同时提高了总体吞吐量。可以配置链接行为; 下图中的示例数据流使用五个子任务执行,因此使用五个并行线程执行。
任务槽和资源
每个工作线程(TaskManager)都是一个JVM进程,可以在单独的线程中执行一个或多个子任务。为了控制 TaskManager 接受的任务数量,它具有所谓的任务槽(至少一个)。
每个任务槽表示任务管理器资源的固定子集。例如,具有三个插槽的 TaskManager 会将其托管内存的 1/3 专用于每个插槽。对资源进行时隙意味着子任务不会与其他作业中的子任务竞争托管内存,而是具有一定量的保留托管内存。请注意,此处不会发生 CPU 隔离;当前插槽仅分隔任务的托管内存。
通过调整任务槽的数量,用户可以定义子任务如何相互隔离。每个 TaskManager 有一个槽意味着每个任务组都在单独的 JVM 中运行(例如,可以在单独的容器中启动)。拥有多个插槽意味着更多的子任务共享相同的 JVM。同一 JVM 中的任务共享 TCP 连接(通过多路复用)和检测信号消息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。
默认情况下,Flink 允许子任务共享插槽,即使它们是不同任务的子任务,只要它们来自同一作业。结果是,一个槽可以容纳作业的整个管道。允许此插槽共享有两个主要好处:
- Flink 集群需要的任务槽数与作业中使用的最高并行度完全相同。无需计算程序总共包含多少个任务(具有不同的并行度)。
- 更容易获得更好的资源利用率。如果没有槽共享,非密集型 source/map() 子任务将阻塞与资源密集型窗口子任务一样多的资源。通过槽共享,将本例中的基本并行度从 2 增加到 6 可充分利用槽化资源,同时确保繁重的子任务在 TaskManagers 之间公平分布。