【Flink快速入门-8.Flink Flink 架构介绍】
Flink 架构介绍
实验介绍
经过前⾯的⼏个实验,相信⼤家已经对 Flink 有了⼀定的认识。但是在学习⼀个技术框架 的时候,除了 API ,我们还必须了解其架构体系,这样我们才会对它有一个更加全面的认识。所以本节实验我们重点来学习 Flink 的架构及其相关组件。
知识点
-
JobManager
-
ResourceManager
-
TaskManager
-
Dispatcher
-
Slots
Flink 中的重要角色
Flink 运行时架构主要包括四个不同的组件,它们会在运行流处理应用程序时协同工作:作业管理器(JobManager)、资源管理器(ResourceManager)、任务管理器(TaskManager),以及分发器(Dispatcher)。因为 Flink 是用 Java 和 Scala 实现的,所以所有组件都会运行在 Java 虚拟机上。每个组件的职责如下:
作业管理器(JobManager)
控制一个应用程序执行的主进程,也就是说,每个应用程序都会被一个不同的 JobManager 所控制执行。JobManager 会先接收到要执行的应用程序,这个应用程序会包括:作业图(JobGraph)、逻辑数据流图(logical dataflow graph)和打包了所有的类、库和其它资源的 JAR 包。JobManager 会把 JobGraph 转换成一个物理层面的数据流图,这个图被叫做“执行图”(ExecutionGraph),包含了所有可以并发执行的任务。JobManager 会向资源管理器(ResourceManager)请求执行任务必要的资源,也就是任务管理器(TaskManager)上的插槽(slot)。一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的 TaskManager 上。而在运行过程中,JobManager 会负责所有需要中央协调的操作,比如说检查点(checkpoints)的协调。
资源管理器(ResourceManager)
主要负责管理任务管理器(TaskManager)的插槽(slot),TaskManger 插槽是 Flink 中定义的处理资源单元。Flink 为不同的环境和资源管理工具提供了不同资源管理器,比如 YARN、Mesos、K8s,以及 standalone 部署。当 JobManager 申请插槽资源时,ResourceManager 会将有空闲插槽的 TaskManager 分配给 JobManager。如果 ResourceManager 没有足够的插槽来满足 JobManager 的请求,它还可以向资源提供平台发起会话,以提供启动 TaskManager 进程的容器。另外,ResourceManager 还负责终止空闲的 TaskManager,释放计算资源。
任务管理器(TaskManager)
Flink 中的工作进程。通常在 Flink 中会有多个 TaskManager 运行,每一个 TaskManager 都包含了一定数量的插槽(slots)。插槽的数量限制了 TaskManager 能够执行的任务数量。启动之后,TaskManager 会向资源管理器注册它的插槽;收到资源管理器的指令后,TaskManager 就会将一个或者多个插槽提供给 JobManager 调用。JobManager 就可以向插槽分配任务(tasks)来执行了。在执行过程中,一个 TaskManager 可以跟其它运行同一应用程序的 TaskManager 交换数据。
分发器(Dispatcher)
可以跨作业运行,它为应用提交提供了 REST 接口。当一个应用被提交执行时,分发器就会启动并将应用移交给一个 JobManager。由于是 REST 接口,所以 Dispatcher 可以作为集群的一个 HTTP 接入点,这样就能够不受防火墙阻挡。Dispatcher 也会启动一个 Web UI,用来方便地展示和监控作业执行的信息。Dispatcher 在架构中可能并不是必需的,这取决于应用提交运行的方式。
Slots
每⼀个 TaskManager(worker)是⼀个 JVM 进程,它可能会在独⽴的线程上执⾏⼀个或多个 subtask。为了控制⼀个 worker 能接收多少个 task,worker 通过 task slot 来进⾏控制(⼀个 worker ⾄少有⼀个 task slot)。每个 task slot 表示 TaskManager 拥有资源的⼀个固定⼤⼩的⼦集。假如⼀个 TaskManager 有三个 slot,那么它会将其管理的内存分成三份给各个 slot。资源 slot 化意味着⼀个 subtask 将不需要跟来⾃其 他 job 的 subtask 竞争被管理的内存,取⽽代之的是它将拥有⼀定数量的内存储备。需要注意的是,这⾥ 不会涉及到 CPU 的隔离,slot ⽬前仅仅⽤来隔离 task 的受管理的内存。
通过调整 task slot 的数量,允许⽤户定义 subtask 之间如何互相隔离。如果⼀个 TaskManager ⼀个 slot,那将意味着每个 task group 运⾏在独⽴的 JVM 中(该 JVM 可能是通过⼀个特定的容器启动的),⽽ ⼀个 TaskManager 多个 slot 意味着更多的 subtask 可以共享同⼀个 JVM。⽽在同⼀个 JVM 进程中的 task 将 共享 TCP 连接(基于多路复⽤)和⼼跳消息。它们也可能共享数据集和数据结构,因此这减少了每个 task 的负载。
Task Slot 是静态的概念,是指 TaskManager 具有的并发执⾏能⼒,可以通过参数 taskmanager.numberOfTaskSlots 进⾏配置,⽽并⾏度 parallelism 是动态概念,即 TaskManager 运⾏ 程序时实际使⽤的并发能⼒,可以通过参数 parallelism.default 进⾏配置。也就是说,假设⼀共有 3 个 TaskManager,每⼀个 TaskManager 中分配 3 个 TaskSlot,也就是每个 TaskManager 可以接收 3 个 task,⼀共 9 个 TaskSlot,如果我们设置 parallelism.default=1,即运⾏程序默认的并⾏度为 1,9 个 TaskSlot 只⽤了 1 个,有 8 个空闲,因此,设置合适的并⾏度才能提⾼效率。
程序与数据流
Flink 程序的基础构建模块是 流(streams) 与 转换(transformations)(需要注意的是,Flink 的 DataSet API 所使⽤的 DataSets 其内部也是 stream)。⼀个 stream 可以看成⼀个中间结果,⽽ ⼀个 transformations 是以⼀个或多个 stream 作为输⼊的某种 operation,该 operation 利⽤这些 stream 进⾏计算从⽽产⽣⼀个或多个 result stream。在运⾏时,Flink 上运⾏的程序会被映射成 streaming dataflows,它包含了 streams 和 transformations operators。每⼀个 dataflow 以⼀个 或多个 sources 开始以⼀个或多个 sinks 结束。dataflow 类似 Spark 的 DAG,当然特定形式的环可以 通过 iteration 构建。在⼤部分情况下,程序中的 transformations 跟 dataflow 中的 operator 是⼀⼀ 对应的关系,但有时候,⼀个 transformation 可能对应多个 operator。
task 与 operator chains
出于分布式执⾏的⽬的,Flink 将 operator 的 subtask 链接在⼀起形成 task,每个 task 在⼀个线程中 执⾏。将 operators 链接成 task 是⾮常有效的优化:它能减少线程之间的切换和基于缓存区的数据 交换,在减少时延的同时提升吞吐量。链接的⾏为可以在编程 API 中进⾏指定
![image-20250208145246255](D:\home\documents\NIIT\2025-1\假期工作\2025-2-11个快速入门Flink\8-Flink 架构介绍.assets\image-20250208145246255.png)
如果你在此之前有学习过 Spark Streaming,我们可以将 Flink 中的术语和 Spark Streaming 中的术语做个类比,方便理解:
Spark Streaming | Flink |
---|---|
DStream | DataStream |
Trasnformation | Trasnformation |
Action | Sink |
Task | SubTask |
Pipeline | Oprator chains |
DAG | DataFlow Graph |
Master + Driver | JobManager |
Worker + Executor | TaskManager |
任务调度流程
当 Flink 集群启动后,首先会启动一个 JobManger 和一个或多个的 TaskManager。由 Client 提交任务给 JobManager,JobManager 再调度任务到各个 TaskManager 去执行,然后 TaskManager 将心跳和统计信息汇报给 JobManager。TaskManager 之间以流的形式进行数据的传输。上述三者均为独立的 JVM 进程。
Client 为提交 Job 的客户端,可以是运行在任何机器上(与 JobManager 环境连通即可)。提交 Job 后,Client 可以结束进程(Streaming 的任务),也可以不结束并等待结果返回。
JobManager 主要负责调度 Job 并协调 Task 做 checkpoint,从 Client 处接收到 Job 和 JAR 包等资源后,会生成优化后的执行计划,并以 Task 的单元调度到各个 TaskManager 去执行。
TaskManager 在启动的时候就设置好了槽位数(Slot),每个 slot 能启动一个 Task,Task 为线程。从 JobManager 处接收需要部署的 Task,部署启动后,与自己的上游建立 Netty 连接,接收数据并处理。
客户端不是运行时和程序执行的一部分,但它用于准备并发送 DataFlow(JobGraph)给 Master(JobManager),然后,客户端断开连接或者维持连接以等待接收计算结果。
总结
本节实验中我们重点介绍了 Flink 的架构内容,主要包括重要的组件以及任务提交流程。本节实验虽然没有代码部分,但是以上概念一定要清楚。因为架构是我们了解一个框架的核心基础,架构特性熟悉之后对我们后续的深⼊研究以及性能调优和排错都有⾮常重要的意义,而且在找工作的时候架构也是面试官的高频考点之一,同学们一定要重视!