Flink部署模式介绍

2,557 阅读10分钟

来自 Flink1.17 版本

Flink是一个分布式系统,需要有效分配和管理计算资源,以执行流式应用程序。它与Hadoop YARN和Kubernetes等所有常见的集群资源管理器集成,也可以设置为 standalone cluster运行甚至作为库(library)运行。

在 Flink1.11 引入 Flink Application Cluster 模式后,现在Flink有三种集群部署模式:

  • Flink Application Cluster
  • Flink Session Cluster
  • Flink Job Cluster (has been deprecated in Flink 1.15)

上述模式的不同之处在于:

  • 集群生命周期和资源隔离保证
  • main()方法是在客户端上执行还是在集群上执行

  • Application Mode:启动一个专用的JobManager来提交作业,JobManager将只执行此作业,然后退出。Flink应用程序在JobManager上运行(即 main() 方法在集群上执行)。
  • Per-Job Mode:启动一个专用的JobManager来提交作业,JobManager将只执行此作业,然后退出。Flink应用程序在提交作业的每个客户端上运行即 main() 方法在客户端上执行)。
  • Session Mode:多个job共享同一个JobManager。

在 Session Mode下,集群生命周期独立于集群上运行的任何作业的生命周期,并且资源在所有作业之间共享。Application Mode 为每个应用程序创建一个会话集群(session cluster),并在集群上执行应用程序的main()方法。因此,它具有更好的资源隔离,因为资源仅由从单个main()方法启动的作业使用。这是以为每个应用程序增加一个专用集群为代价的。

Flink Cluster

Flink运行时由两种类型的进程组成:一个JobManager和一个或多个TaskManagers。

The Client is not part of the runtime and program execution, but is used to prepare and send a dataflow to the JobManager.

Client(客户端)不是运行时和程序执行的一部分,它主要用于准备向JobManager发送数据流。

Client(客户端) 发送完数据流之后就可以断开连接(分离模式),或保持连接以接收进度报告(连接模式)。

Client(客户端)要么在代码中触发Java/Scala程序运行;要么在命令行进程中运行./bin/flink run 

JobManager 和 TaskManagers 可以通过各种方式启动:

  • directly on the machines as a standalone cluster. 直接在机器上作为 standalone 集群启动。
  • n containers, or managed by resource frameworks like YARN. 在容器中启动、通过YARN资源框架启动。

TaskManagers 连接 JobManagers宣布自己可用并且被分配任务。

JobManager

JobManager 负责协调Flink应用程序的分布式执行情况。决定何时安排下一个任务(或一组任务),对完成的任务或执行失败的任务做出反应,协调检查点,协调故障恢复等。这个过程由三个不同的部分组成:

  • ResourceManager:负责Flink集群中的资源分配和调配。管理 task slots(是Flink集群中资源调度的单位),Flink为不同的环境和资源提供商(如YARN、Kubernetes和 standalone 部署)实现了了对应的 ResourceManager。在 standalone 设置中,ResourceManager只能为可用的TaskManager分配slots,而不能单独启动新的TaskManager。
  • Dispatcher:提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。
  • JobMaster:一个 JobMaster 负责管理单个 JobGraph 的执行。Flink集群中可以同时运行多个作业,每个作业都有自己的 JobMaster。

搭建 Flink 集群至少要有一个JobManager;搭建高可用(HA)时需要配置多个JobManagers(至少2个),其中一个是leader,其余的是 standby。

TaskManagers

TaskManagers(也称为 workers)是执行 dataflow task ,并且缓存和交换数据流。 集群中始终至少要有一个 TaskManager,在 TaskManager 中资源调度的最小单位是 task slot。TaskManager中任务槽的数量表示并发处理任务的数量。请注意,多个运算符(算子)可能在同一个 task slot 中执行

Tasks 和 算子链

对于分布式执行,Flink 将算子的 subtasks 链接成 tasks。每个 task 由一个线程执行。将算子链接成 task 是个有用的优化:它减少了线程间切换和缓冲的开销,并在降低延迟的同时提高了整体吞吐量。

下图中的示例数据流通过五个子任务执行,因此使用五个并行线程执行。

Task Slots 和资源

每个 worker(TaskManager)都是一个 JVM 进程。可以在单独的线程中执行一个或多个subtasks,为了控制TaskManager接受任务的数量,就有了所谓的 task slots(至少一个)。

每个 task slot 代表 TaskManager 中资源的固定子集。例如,有三个slot 的TaskManager 将把1/3的托管内存用于每个slot。分配资源意味着子任务不会与其他作业的子任务争夺托管内存,而是保留一定数量的托管内存。请注意,这里没有发生CPU隔离;当前slot仅分离任务的托管内存。

通过调整 task slot 的数量,用户可以定义如何将 subtask 彼此隔离。

每个TaskManager有一个 slot 意味着每个任务组(task group)都在一个单独的 JVM 中运行(例如,可以在一个独立的容器中启动)。拥有多个slots意味着多个 subtask 共享同一个 JVM。同一个JVM中的 tasks 共享TCP连接(通过多路复用)和心跳信息( heartbeat messages)。它们还可以共享数据集和数据结构,从而减少每个任务的开销。

默认情况下,Flink允许 subtasks 共享slots,即使它们是不同 tasks的subtasks,只要他们来自同一个 Job。结果是,一个slot可以容纳整个工作pipeline。允许此 slot 共享有两个主要好处:

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

Flink Application Execution

Flink Application 是从其 main() 方法产生的一个或多个 Flink 作业的任何用户程序。这些作业的执行可以发生在本地JVM(LocalEnvironment)中,也可以发生在具有多台机器的集群的远程设置(RemoteEnvironment)中。对于每个程序,ExecutionEnvironment 提供了一些方法来控制作业执行(例如设置并行度)并与外界交互。

Flink Application 的作业可以提交到长期运行的Flink Session Cluster、专用的 Flink Job Cluster(已弃用)或Flink Application Cluster.。它们之间的区别主要与集群的生命周期( cluster’s lifecycle)和资源隔离(resource isolation )保证有关。

Flink Application Cluster

  • Cluster Lifecycle(集群生命周期):Flink Application Cluster 是一个专用的Flink集群,它只执行来自一个Flink应用的作业,并且main()方法在集群上运行,而不是在客户端上运行。提交作业是一个单步骤过程:无需先启动 Flink 集群,然后将作业提交到现有的 session 集群;相反,将应用程序逻辑和依赖打包成一个可执行的作业 JAR 中,并且集群入口(ApplicationClusterEntryPoint)负责调用 main()方法来提取 JobGraph。它允许像在Kubernetes上部署任何其他应用程序一样部署Flink应用程序。因此,Flink应用程序集群的生存期与Flink应用的生存期相绑定。The lifetime of a Flink Application Cluster is therefore bound to the lifetime of the Flink Application.
  • Resource Isolation(资源隔离):在 Flink Application 集群中,ResourceManager 和 Dispatcher 作用于单个的 Flink 应用程序,相比于 Flink Session 集群,它提供了更好的隔离。

Flink Session Cluster

  • Cluster Lifecycle(集群生命周期):在 Flink Session Cluster 中,客户端连接到一个预先存在的、长期运行的集群,该集群可以接受多个作业提交。即使在所有作业完成后,Cluster(JobManager)仍将继续运行,直到手动停止会话。因此,Flink会话集群的生存期不与任何Flink作业的生存期绑定。
  • Resource Isolation(资源隔离):TaskManager slots 由ResourceManager在作业提交时分配,并在作业完成后释放。因为所有job 都共享同一个集群,所以在提交job阶段存在一些集群资源竞争,比如网络带宽。这种共享集群设置的一个限制是,如果一个TaskManager崩溃,那么所有在该TaskManager上运行任务的作业都将失败;同样,如果JobManager上发生一些致命错误,它将影响集群中运行的所有作业。
  • Other considerations(其他注意事项):拥有预先存在的集群可以节省大量的资源申请和启动TaskManagers的时间。这一点在作业执行时间非常短且启动时间过长会对端到端用户体验产生负面影响的情况下很重要,短查询的交互式分析就是如此,在这种情况下,作业可以使用现有资源快速执行计算。

Formerly, a Flink Session Cluster was also known as a Flink Cluster in session mode. 以前,Flink会话集群也称为会话模式下的Flink集群。

Flink Job Cluster (deprecated)

Per-job mode has been deprecated in Flink 1.15. Please consider application mode to launch a dedicated cluster per-job on YARN. Per-job mode 在Flink 1.15中已被弃用。请考虑在YARN上为每个作业启动专用集群的应用程序模式。

  • Cluster Lifecycle:在 Flink Job Cluster 中,可用的集群管理器(例如 YARN)用于为每个提交的作业启动一个集群,并且该集群仅可用于该作业。在这里,Client(客户端)首先从集群管理器请求资源以启动JobManager,并将作业提交给在此进程中运行的 Dispatcher。然后,任务管理器会根据作业的资源需求进行延迟分配。一旦作业完成,Flink作业集群就会被拆除。
  • Resource Isolation:JobManager中的致命错误只会影响在该Flink作业集群中运行的一个作业。
  • Other considerations(其他注意事项):由于 ResourceManager 必须等待外部资源管理组件来申请启动TaskManager进程和分配资源,Flink Job Clusters更适合于长时间运行、稳定性要求高且对较长启动时间不敏感的大型作业。

Flink 任务提交方式

  1. Local 模式:本地测试使用
  2. StandaLone 模式:为Flink 集群的单机版提交方式,只使用一个节点进行提交,常用 Session 模式;同时 Standalone 可配置 HA 高可用提交,使用多个节点。
  3. Yarn 模式:在生产环节中使用最多,yarn 模式又包含三种模式:
  • yarn Session 模式
  • yarn per job 模式
  • yarn application 模式
  1. K8S 模式

yarn 提交方式的特点,因为在生产环境中绝大多数公司都使用 yarn 来管理资源,所以就以yarn提交方式进行重点介绍:

  1. yarn Session 模式:所有作业共享集群资源,隔离性差,JVM 负载瓶颈,main() 方法在客户端执行,适合执行时间短、频繁执行的短任务,集群中的所有作业只有一个 JobManager,另外 job 被随机分配给 TaskManager。

特点:yarn Session 模式需要先启动集群,然后再提交作业。

  1. yarn per job 模式:每个作业单独启动集群、隔离性好、JVM 负载均衡、mian() 方法在客户端执行。在 per job 模式下,每个 Job 都有一个JobManager,每个TaskManager 只有一个Job。

特点:一个任务(task)只会对应一个Jon,每提交一个作业都会根据自身情况单独向 yarn 申请资源,独享 Dispatcher 和 ResourceManager,按需接受资源申请,适合规模大、运行时间长的作业。

  1. yarn application 模式:mian() 方法在 JobManager中执行,入口点位于 ApplicationClusterEntryPoint,客户端只需要负责发起部署请求。

特点:极大缓解了客户端压力,避免资源成为一个瓶颈。