0


Flink系统架构和应用部署方式

概述

Flink傲立于分布式系统的前沿,它的执行流应用程序能力深受瞩目,而这一切成就的背后,离不开对计算资源的精妙分配与高效管理。作为一款卓越的分布式系统,Flink深知计算资源对于其性能与效率的至关重要性。

尤为值得一提的是,Flink展现了卓越的兼容性,它无缝集成了诸如Hadoop YARN、Apache Mesos以及Kubernetes等一系列广受欢迎的集群资源管理器。这不仅意味着Flink能够轻松驾驭这些主流平台,实现资源的灵活调度与优化,还进一步拓宽了其应用场景。除此之外,Flink同样具备强大的灵活性,它既可以作为独立的集群自主运行,又能以库的形式嵌入到其他系统中,满足多样化的使用需求。

综上所述,Flink不仅是一款功能强大的分布式系统,更是一个能够与多种集群资源管理器紧密协作、灵活适应各种场景的杰出代表。

本文概述了 Flink 的架构,并且描述了其主要组件如何进行交互以及Flink应用程序的几种部署方式和从故障中恢复的机制。

Flink集群架构组件

Flink的运行时架构精妙而高效,其核心由两大类型的进程协同工作,共同支撑起流/批处理任务的稳定运行。这两个关键组件分别是:一个高瞻远瞩的JobManager,以及一个或多个勤勤恳恳的TaskManager。

JobManager与TaskManager的启动方式灵活多样,既可以直接在物理或虚拟机器上以standalone集群的形式独立启动,也可以在容器化环境中优雅地运行,甚至还能借助YARN、Kubernetes、Mesos等强大的资源管理框架进行动态管理与启动。一旦TaskManager成功启动,它会主动连接到JobManager,宣告自身的可用性,并随时准备接收由JobManager分配的工作负载。这种设计不仅提升了资源的利用率,还确保了作业调度与执行的灵活性与高效性。

Client

在Flink的运作体系中,Client并不直接参与运行时的数据处理或程序执行流程,而是扮演着数据流的准备者与发送者的角色。Client的主要职责是构建并配置数据流,随后将其提交给JobManager以启动处理流程。这一提交过程完成后,Client可以选择两种模式进行操作:在分离模式下,Client会与集群断开连接,释放资源并允许用户进行其他任务;而在附加模式下,Client则保持与集群的连接,持续接收并展示作业的执行状态与报告。

Client的启动方式灵活多样,既可以作为Java/Scala程序的一部分被触发执行,让开发者能够在代码中直接配置并提交作业;也可以通过命令行界面(如执行

./bin/flink run ...

命令)来运行,为不熟悉编程的用户提供了便捷的提交途径。无论采用哪种方式,Client都以其独特的功能,为Flink作业的顺利启动与监控提供了有力支持。

JobManager

JobManager在Flink应用程序的分布式执行过程中扮演着至关重要的协调者角色。它负责决定task(或task集合)的调度时机,监控task的完成情况并对执行失败做出及时响应。此外,JobManager还负责协调checkpoint的创建,以确保数据的一致性与可恢复性,并在作业失败时指导从先前状态进行恢复。通过这些职责的履行,JobManager确保了Flink应用程序能够高效、可靠地运行。JobManager主要由下面的三个不同的组件组成:

  • ResourceManager: ResourceManager在Flink集群中扮演着资源管理的核心角色,它负责资源的供应、回收以及分配任务。它管理的核心资源单位是task slots(TaskManager小节会介绍),这些slots是Flink集群进行资源调度的基础。为了满足不同环境和资源提供者的需求,Flink为YARN、Mesos、Kubernetes以及standalone部署等场景分别实现了特定的ResourceManager。值得注意的是,在standalone模式下,ResourceManager的功能受限于仅能对已存在的TaskManager的slots进行分配,而无法自主启动新的TaskManager实例。
  • Dispatcher:Dispatcher通过一个REST接口接收Flink应用程序的执行请求,并为每个提交的Flink应用程序实例化一个新的JobMaster以启动执行。此外,它还承载着Flink的Web用户界面(WebUI),该界面为用户提供Flink应用程序执行状态的实时信息。
  • JobMaster:JobMaster的职责是监督并管理单个JobGraph的执行流程。在Flink集群的运行环境中,能够并行处理多个Flink应用程序,而每个Flink应用程序都配备有专属的JobMaster来负责其执行管理。

始终至少有一个 JobManager。高可用(HA)设置中可能有多个 JobManager,其中一个始终是 leader,其他的则是 slave。

TaskManagers

TaskManager(也称为 worker)执行作业流的 task,并且缓存和交换数据流。

必须始终至少有一个 TaskManager。在 TaskManager 中资源调度的最小单位是 task slot。TaskManager 中 task slot 的数量表示并发处理 task 的数量。请注意一个 task slot 中可以执行多个算子。其主要包含以下的一些组件:

  • TaskSlotTable: 管理TaskSlot的组件,负责添加和获取Task、申请和释放Slot等操作。
  • ResourceManager:TaskManager向ResourceManager申请插槽资源,ResourceManager负责资源的提供、回收、分配和管理。
  • HeartbeatManager:包含JobManagerHeartbeatManager和ResourceManagerHeartbeatManager,负责检测与JobManager和ResourceManager的心跳连接,以确保通信的顺畅和集群的稳定性。
  • BlobService:提供BLOB(Binary Large Object)的存储服务,包括可恢复的PermanentBlobService和不可恢复的TransientBlobService。BLOB底层存储支持多种实现,如HDFS、S3、FTP等。

算子、Task和Subtask三者关系

概念

  • 算子(Operator)

    • 算子表示一种数据流的转换操作,它用于对输入流进行转换并生成一个新的数据流作为输出。- 算子可以执行各种数据处理操作,如过滤、映射、聚合、连接、排序等。- Flink提供了许多内置的算子,如map、filter、keyBy等,同时也允许用户自定义算子以满足特定的需求。
  • Task

    • 在Flink中,Task是作业(Job)拆解后(Dataflow Graph)的最小执行单元,它负责执行具体的计算逻辑。- 一般情况下,每个Task对应着作业中特定运算步骤的一个实例,比如map、filter、join等操作。- 在发生Operator Chain情况下,一个Task可能包含多个算子的操作逻辑。
  • SubTask

    • Subtask是Flink中任务的最小执行单元,它是Task的一个并行实例。- 当一个算子(Operator)设置了一个大于1的并行度时,该算子会被拆分成多个Subtasks,这些Subtasks分布在不同的Task Slots中并行执行。- Subtask是Flink进行资源分配和调度的基本单位。

算子和Task的关系

  • 在没有Operator Chain的情况下,一个算子通常对应一个Task。但是,当多个算子被链接在一起时(通过Flink的算子链机制),它们可能会在同一个Task中执行,以减少中间数据的交换开销。
  • 在实际应用中,一个Task可能包含多个算子的操作逻辑,这些算子在Task内部以流水线的方式执行。

Task和SubTask的关系

  • 在没有并行度设置或并行度为1的情况下,一个Task通常只包含一个Subtask。
  • 当并行度大于1时,一个Task会被拆分成多个Subtasks,这些Subtasks在Flink集群中并行执行。
  • 需要注意的是,虽然多个Subtasks并行执行,但它们都属于同一个Task,并共享该Task的计算逻辑和状态。

算子和SubTask的关系

SubTask是算子的执行实例。

样例

下图中样例数据流用 5 个 subtask 执行,因此有 5 个并行线程。

Task Slots和资源的关系

每个 TaskManager(工作管理器)作为一个独立的 JVM 进程运行,能够在其内部的独立线程上并发执行一个或多个Subtask。为了管理一个 TaskManager 能够承载的任务数量,引入了所谓的任务槽(Task Slots)概念,每个 TaskManager 至少配备一个任务槽。

每个任务槽(Task Slot)象征着TaskManager内部一组固定的资源分配单元。举例来说,一个配置了3个任务槽的TaskManager,会将其所管理的托管内存均分为三份,每份分配给一个任务槽。这种资源分配确保了子任务(Subtask)在运行时不会与其他作业的子任务争夺托管内存资源,因为每个子任务都被分配了一定数量的专用托管内存。需要指出的是,这里并未实现CPU资源的隔离;当前的Task Slot仅仅是在TaskManager的托管内存层面为任务划分了界限。

通过调整 Task Slot 的数量,用户可以定义 Subtask 如何互相隔离。每个 TaskManager 有一个 Slot,这意味着每个 Task 组都在单独的 JVM 中运行(例如,可以在单独的容器中启动)。具有多个 Slot 意味着更多 Subtask 共享同一 JVM。同一 JVM 中的 Task 共享 TCP 连接(通过多路复用)和心跳信息。它们还可以共享数据集和数据结构,从而减少了每个 Task 的开销。

默认情况下,Flink 允许 Subtask 共享 Slot,即便它们是不同的 Task 的 Subtask,只要是来自于同一作业即可。结果就是一个 Slot 可以持有整个作业Subtask执行的管道。允许Slot主要有以下两个主要的有点:

  • Flink 集群所需的 task slot 和作业中使用的最大并行度恰好一样。无需计算程序总共包含多少个 task(具有不同并行度)。
  • 容易获得更好的资源利用。如果没有 slot 共享,非密集 subtask(source/map())将需要和密集型 subtask(window) 一样多的资源。通过 slot 共享,我们示例中的基本并行度从 2 增加到 6,可以充分利用分配的资源,同时确保繁重的 subtask 在 TaskManager 之间公平分配。

Flink应用程序部署

Flink 应用程序,作为源自其

main()

方法的用户程序,能够孕育出一个或多个 Flink 作业。这些作业的执行舞台既可以是本地的 JVM(即

LocalEnvironment

),也能够扩展到由多台机器构成的远程集群环境(即

RemoteEnvironment

)。对于每一份精心编写的程序,

ExecutionEnvironment

提供了丰富的方法来控制作业的执行细节,比如设定并行度、Checkpoint时间间隔等,并提供了一些方法能够与外界进行交互。

Flink 应用程序的作业具备多种部署选项,它们可以投递至持续运行的 Flink Session 集群、专享的 Flink Job 集群,或是 Flink Application 集群中执行。这些部署方式的核心差异,主要在于它们对集群生命周期的管理以及所提供的资源隔离保障各不相同。

Flink Session 集群

  • 集群生命周期:在Flink Session集群中,客户端与一个已经存在并持续运行的集群建立连接,这个集群具备接收多个作业提交的能力。即便所有提交的作业都已完成其执行,集群(包括其中的JobManager)仍会保持运行状态,除非用户手动终止这个session。这意味着,Flink Session集群的运行时间并不依赖于任何单一作业的寿命,而是由用户的操作来决定。
  • 资源隔离:TaskManager的slot是由ResourceManager在作业提交时动态分配的,并在作业结束后被释放回系统。由于多个作业共同使用一个集群,因此在集群资源(如网络带宽等)的分配上会存在一定的竞争。这种共享资源的模式存在一个局限性:如果某个TaskManager发生故障,那么在该TaskManager上运行的所有任务所属的作业都会受到影响并失败;同样地,如果JobManager遭遇严重错误,那么整个集群中正在运行的所有作业都将受到波及。
  • 应用场景:预先存在的集群能够显著提升资源申请与TaskManager启动的效率。对于那些作业执行时间短但启动时间长的情况,其对端到端用户体验的负面影响尤为显著,特别是在交互式分析场景中,用户期望的是能够快速利用现有资源完成计算任务。拥有一个始终在线的集群,可以确保这些短作业能够迅速获得所需资源并高效执行,从而提升用户体验。

Flink Job 集群

  • 集群生命周期:在Flink Job集群模式下,我们利用集群管理器(例如YARN)来为每个提交的作业单独启动一个集群,这个集群是专属于该作业的。流程是这样的:客户端首先会向集群管理器请求资源,用以启动JobManager;随后,作业会被提交给在这个新启动的JobManager进程中运行的Dispatcher。接着,根据作业的实际资源需求,TaskManager会被惰性地分配。当作业执行完毕后,整个Flink Job集群会被自动拆除和清理。
  • 资源隔离:JobManager 中的致命错误仅影响在 Flink Job 集群中运行的一个作业。
  • 应用场景:由于 ResourceManager 必须应用并等待外部资源管理组件来启动 TaskManager 进程和分配资源,因此 Flink Job 集群更适合长期运行、具有高稳定性要求且对较长的启动时间不敏感的大型作业。

Flink Application 集群

  • 集群生命周期:Flink Application 集群是一种专门为运行 Flink 应用程序而设计的集群,它直接从应用程序执行作业,且其 main() 方法是在集群环境中执行,而非客户端。在作业提交过程中,无需预先启动 Flink 集群,再将作业部署到已存在的session集群中;这一过程被简化为一步:将应用程序逻辑及其依赖项打包为一个可执行的 JAR 文件,随后由集群的入口点(即 ApplicationClusterEntryPoint)负责启动 main() 方法,从而生成并运行 JobGraph。这种模式使得 Flink 应用程序的部署变得非常灵活,例如,可以像在其他平台(如 Kubernetes)上部署普通应用程序一样进行部署。因此,Flink Application 集群的生命周期与其承载的 Flink 应用程序的生命周期紧密相连。
  • 资源隔离:在 Flink Application 集群中,ResourceManager 和 Dispatcher 作用于单个的 Flink 应用程序,相比于 Flink Session 集群,它提供了更好的隔离。
  • 应用场景:Flink Job 集群可以看做是 Flink Application 集群”客户端运行“的替代方案。因此其应用场景和Flink Job集群的应用场景相似。

本文转载自: https://blog.csdn.net/MCC_MCC_MCC/article/details/142906744
版权归原作者 吾鳴 所有, 如有侵权,请联系我们删除。

“Flink系统架构和应用部署方式”的评论:

还没有评论