Flink 之部署篇
Flink 是一个多用途框架,支持多种不同的混合部署方案。下面,我们将简要介绍 Flink 集群的构建模块、它们的用途和可用实现。如果您只想在本地启动 Flink,我们建议您建立一个独立集群(
Standalone Cluster
)。
1.概述和参考架构
下图显示了每个 Flink 集群的构件。总有一个客户端在运行,它接收 Flink 应用程序的代码,将其转换为 JobGraph 并提交给 JobManager。
JobManager 会将工作分配给 TaskManager,实际的算子(如
sources
,
transformations
和
sinks
等)就在 TaskManager 上运行。
部署 Flink 时,每个构件通常有多个可用选项。我们在下表列出了这些选项。
组件
作用
实现
Flink Client将批处理或流应用程序编译成数据流图,然后提交给 JobManager。1️⃣ Command Line Interface
2️⃣ REST Endpoint
3️⃣ SQL Client
4️⃣ Python REPLJobManagerJobManager 是 Flink 中央工作协调组件的名称。它为不同的资源提供者提供不同的实现,这些实现在高可用性、资源分配行为和支持方面各不相同。
作业提交的 JobManager 模式:
(1)Application 模式:专门为一个应用程序运行集群。作业的
main
方法(或客户端)在 JobManager 上执行。支持在一个应用程序中多次调用
execute
/
executeAsync
。
(2)Per-Job 模式:只为一个作业运行集群。作业的
main
方法(或客户端)仅在集群创建之前运行。
(3)Session 模式:一个 JobManager 实例管理多个作业,共享同一个任务管理器集群。1️⃣ Standalone(这是裸机模式,只需要启动 JVM。在此模式下,可通过手动设置使用 Docker、Docker Swarm / Compose、 non-native Kubernetes 和其他模式进行部署)
2️⃣ Kubernetes
3️⃣ YARNTaskManager任务管理器是实际执行 Flink 作业的服务。外部组件
作用
实现
High Availability Service ProviderFlink 的 JobManager 可在高可用性模式下运行,这使得 Flink 能够从 JobManager 故障中恢复。为了更快地进行故障切换,可以启动多个备用 JobManager 作为备份。1️⃣ Zookeeper
2️⃣ Kubernetes HAFile Storage and Persistency对于检查点(流作业的恢复机制),Flink 依赖于外部文件存储系统请参阅 “文件系统” 页面Resource ProviderFlink 可通过不同的资源提供者框架(如 Kubernetes 或 YARN)进行部署。参见上文的 JobManager 实现。Metrics StorageFlink 组件可报告内部指标,Flink 作业也可报告额外的特定作业指标。请参阅 “指标报告器” 页面Application-level data sources and sinks虽然从技术上讲,应用级数据源和汇并不是 Flink 集群组件部署的一部分,但在规划新的 Flink 生产部署时,应考虑到这一点。将常用数据与 Flink 同地放置可带来显著的性能优势。例如:
1️⃣ Apache Kafka
2️⃣ Amazon S3
3️⃣ Elasticsearch
4️⃣ Apache Cassandra
请参阅 “连接器” 页面
2.可重复的资源清理
一旦作业达到 完成、失败 或 取消 的全局终端状态,与作业相关的外部组件资源就会被清理。如果资源清理失败,Flink 会尝试重试清理。您可以配置所使用的重试策略。重试次数达到最大值而不成功,会使作业处于脏状态。其工件需要手动清理(更多详情,请参阅 High Availability Services / JobResultStore 部分)。重新启动相同的作业(即使用相同的作业 ID)将导致清理工作被重新启动,而不会再次运行作业。
3.部署模式
Flink 的部署模式有
Application
、
Per-Job
和
Session
模式。三者的主要区别:
- 1️⃣ 集群与作业的生命周期是否一致。
- 2️⃣ 资源的隔离程度。
- 3️⃣ 作业的
mian()
运行在 Client 还是集群上。
3.1 Application 模式
- 将启动一个专用的 JobManager 来提交作业。JobManager 将只执行此作业,然后退出。Flink 应用程序在 JobManager 上运行。
- 作业与 Flink 集群打包在一起,在 JobManager 启动的时候会执行作业的
main
函数直接启动作业,而不需要通过 Flink Client 提交作业。 - 作业的生命周期与 Flink 集群的一致,即作业关闭后 Flink 集群也会关闭。
在所有其他模式下,应用程序的
main()
方法都在客户端执行。这一过程包括在本地下载应用程序的依赖项,执行
main()
以提取 Flink 运行时可以理解的应用程序表示(即 JobGraph),并将依赖项和 JobGraph 发送到集群。这就使客户端成为资源消耗大户,因为它可能需要大量网络带宽来下载依赖项并将二进制文件发送到集群,还需要 CPU 周期来执行
main()
。当客户端被多个用户共享时,这一问题会更加突出。
在此基础上,
Application
模式为每个提交的应用程序创建一个集群,但这次应用程序的
main()
方法由 JobManager 执行。为每个应用程序创建一个集群可视为创建一个会话集群,仅在特定应用程序的作业之间共享,并在应用程序结束时关闭。通过这种架构,应用程序模式可提供与
Per-Job
模式相同的资源隔离和负载平衡保证,但其粒度为整个应用程序。
应用程序模式基于这样一个假设:所有需要访问用户
jars
的 Flink 组件(JobManager、TaskManager)的类路径(
usrlib
文件夹)上都有用户
jars
。换句话说,您的应用程序与 Flink 发行版捆绑在一起。这样,
Application
模式就不必像其他部署模式那样通过 RPC 向 Flink 组件分发用户
jars
,从而加快了部署 / 恢复过程。
Application 模式假定用户
jars
与 Flink 发行版捆绑在一起。在集群上执行
main()
方法可能会对您的代码产生其他影响,例如您使用
registerCachedFile()
在环境中注册的任何路径都必须能被应用程序的 JobManager 访问。
与
Per-Job
(已废弃)模式相比,
Application
模式允许提交由多个作业组成的应用程序。作业的执行顺序不受部署模式的影响,但受用于启动作业的调用的影响。
execute()
是阻塞式的,它会建立一个顺序,并导致 “下一个” 作业的执行被推迟,直到 “这个” 作业完成。使用
executeAsync()
(非阻塞)会导致 “下一个” 作业在 “这个” 作业完成前开始执行。
应用模式允许
multi-execute()
应用,但在这种情况下不支持高可用性。应用模式下的高可用性仅支持
single-execute()
应用程序。此外,当应用程序模式下多个正在运行的作业(例如使用
executeAsync()
提交的作业)中的任何一个被取消时,所有作业都将停止,而 JobManager 也将关闭。支持常规作业完成(通过源关闭)。
3.2 Per-Job 模式(已废弃)
- 将启动一个专用的 JobManager 来提交作业。JobManager 将只执行此作业,然后退出。Flink 应用程序在提交每个作业集群的客户端上运行。
- 作业与 Flink 集群不是打包在一起,在 JobManager 启动后需要通过 Flink Client 提交作业,即增加了网络传输的压力和客户端的 CPU 资源。
Per-Job
模式仅受 YARN 支持,在 Flink
1.15
中已被弃用。它将在 FLINK-26000 中被弃用。请考虑使用
Application
模式在 YARN 上按任务启动专用集群。
为了提供更好的资源隔离保证,
Per-Job
模式使用可用的资源提供者框架(如 YARN)为每个提交的作业启动一个集群。该集群只对该作业可用。当作业完成后,集群会被拆除,任何残留的资源(文件等)都会被清除。这提供了更好的资源隔离,因为行为不端的作业只能导致其自身的 TaskManager 宕机。此外,由于每个作业都有一个 TaskManager,它还能将记账的负担分散到多个 TaskManager 中。
🚀
Application
模式对比
Per-Job
模式最大的区别是,前者使用
executeAsync()
提交作业(不阻塞),而后者使用
execute()
提交作业(阻塞),因此
Application
模式可以运行多个作业。
3.3 Session 模式
- 多个作业共享一个 JobManager。
- 常驻的 JobManager,多个作业共享同一个集群。如果其中一个作业异常导致 TaskManager 关闭,则该 TM 上的全部作业都会重新调度。
Session 模式假定有一个已在运行的集群,并使用该集群的资源来执行任何已提交的应用程序。在同一(Session)集群中执行的应用程序使用相同的资源,因此也会竞争相同的资源。这样做的好处是,您无需为每个提交的作业支付启动整个集群的资源开销。但是,如果其中一个作业出现问题或导致 TaskManager 宕机,那么在该 TaskManager 上运行的所有作业都会受到故障影响。这除了会对导致故障的作业造成负面影响外,还意味着所有重新启动的作业都会同时访问文件系统,从而导致其他服务无法使用文件系统,这就意味着潜在的大规模恢复过程。此外,单个集群运行多个作业意味着 JobManager 要承担更多的负荷,因为它要负责管理集群中的所有作业。
版权归原作者 G皮T 所有, 如有侵权,请联系我们删除。