Flink 是一个多功能框架,以混合搭配的方式支持许多不同的部署场景。
下面,我们简要介绍 Flink 集群的构建块、它们的用途和可用的实现。 如果你只是想在本地启动 Flink,我们建议设置一个 Standalone Cluster。
概述和参考架构
下图展示了每个 Flink 集群的构建块。 总有一个客户端在运行。 它获取 Flink 应用程序的代码,将其转换为 JobGraph 并提交给 JobManager。
JobManager 将工作分配到 TaskManagers 上,实际操作符(例如源、转换和接收器)正在运行。
在部署 Flink 时,每个构建块通常有多个选项可用。 我们在图下方的表格中列出了它们。
组件 | 目的 | 实现 |
---|---|---|
Flink Client | 将批处理或流式应用程序编译成数据流图,然后将其提交给 JobManager。 | Command Line Interface REST Endpoint SQL Client Python REPL |
JobManager | JobManager 是 Flink 的中心工作协调组件的名称。 它具有针对不同资源提供者的实现,它们在高可用性、资源分配行为和支持的作业提交模式方面有所不同。 作业提交的 JobManager 模式: 应用模式:专为一个应用运行集群。 作业的主要方法(或客户端)在 JobManager 上执行。 支持在应用程序中多次调用 execute /executeAsync 。Per-Job 模式:专门为一项作业运行集群。 作业的主要方法(或客户端)仅在集群创建之前运行。 会话模式:一个 JobManager 实例管理共享同一个 TaskManager 集群的多个作业 |
standalone YARN Kubernetes |
TaskManager | TaskManager 是实际执行 Flink 作业工作的服务。 |
扩展组件(全部可选)
高可用服务 | Flink 的 JobManager 可以在高可用模式下运行,这允许 Flink 从 JobManager 故障中恢复。 为了更快地进行故障转移,可以启动多个备用 JobManager 作为备份。 | Zookeeper Kubernetes HA |
---|---|---|
文件存储与持久化 | 对于检查点(流式作业的恢复机制),Flink 依赖于外部文件存储系统 | See FileSystems page. |
资源提供 | Flink 可以通过不同的 Resource Provider Framework 进行部署,例如 Kubernetes 或 YARN。 | See JobManager implementations above. |
监控存储 | Flink 组件报告内部指标,Flink 作业也可以报告额外的、特定于作业的指标。 | See Metrics Reporter page. |
应用程序级数据源和接收器 | 虽然应用程序级别的数据源和接收器在技术上不是 Flink 集群组件部署的一部分,但在规划新的 Flink 生产部署时应该考虑它们。 使用 Flink 托管常用数据可以带来显着的性能优势 | For example:
1 Apache Kafka See Connectors page. |
可重复资源清理
一旦作业达到完成、失败或取消的全局终端状态,与作业关联的外部组件资源就会被清理。 如果清理资源失败,Flink 将尝试重试清理。 您可以配置使用的重试策略。 达到最大重试次数但未成功将使作业处于脏状态。 它的工件需要手动清理(有关更多详细信息,请参阅高可用性服务/JobResultStore 部分)。 重新启动同一个作业(即使用相同的作业 ID)将导致清理重新启动,而无需再次运行该作业。
目前清理 CompletedCheckpoints 时存在一个问题,这些问题在将它们包含在通常的 CompletedCheckpoint 管理中时未能被删除。 这些工件没有被可重复的清理所覆盖,即它们仍然必须手动删除。 FLINK-26606 涵盖了这一点。
部署模式
Flink 可以通过以下三种方式之一执行应用程序:
- in Application Mode,
- in a Per-Job Mode,
- in Session Mode.
上述模式的不同之处在于:
- 集群生命周期和资源隔离保证
- 应用程序的 main() 方法是在客户端还是在集群上执行。
Application模式
在所有其他模式下,应用程序的 main() 方法在客户端执行。 这个过程包括在本地下载应用程序的依赖项,执行 main() 以提取 Flink 运行时可以理解的应用程序表示(即 JobGraph),并将依赖项和 JobGraph(s) 发送到集群。 这使得客户端成为一个沉重的资源消耗者,因为它可能需要大量的网络带宽来下载依赖项并将二进制文件发送到集群,以及执行 main() 的 CPU 周期。 当客户端在用户之间共享时,这个问题会更加明显。
基于此观察,Application模式为每个提交的应用程序创建一个集群,但这一次,应用程序的 main() 方法在 JobManager 上执行。 为每个应用程序创建一个集群可以看作是创建一个会话集群,它只在特定应用程序的作业之间共享,并在应用程序完成时拆除。 使用这种架构,应用程序模式在整个应用程序的粒度上提供与 Per-Job 模式相同的资源隔离和负载平衡保证。 在 JobManager 上执行 main() 可以节省所需的 CPU 周期,还可以节省本地下载依赖项所需的带宽。 此外,它允许更均匀地分散网络负载以下载集群中应用程序的依赖项,因为每个应用程序都有一个 JobManager。
在应用程序模式中,main() 是在集群上执行的,而不是在客户端上执行的,就像在其他模式中一样。 这可能对您的代码有影响,例如,您使用 registerCachedFile() 在环境中注册的任何路径都必须可由应用程序的 JobManager 访问。
与 Per-Job 模式相比,Application Mode 允许提交由多个作业组成的应用程序。 作业执行的顺序不受部署模式的影响,但受用于启动作业的调用影响。 使用阻塞的 execute() 建立一个顺序,这将导致“下一个”作业的执行被推迟到“这个”作业完成。 使用非阻塞的 executeAsync() 将导致“下一个”作业在“此”作业完成之前开始。
Application模式允许 multi-execute() 应用程序,但在这些情况下不支持高可用性。 Application模式下的高可用性仅支持单次执行()应用程序。
此外,当Application模式下多个正在运行的作业(例如使用 executeAsync() 提交)中的任何一个被取消时,所有作业都将停止并且 JobManager 将关闭。 支持定期完成作业(通过关闭源)。
Per-Job 模式
为了提供更好的资源隔离保证,Per-Job 模式使用可用的资源提供者框架(例如 YARN、Kubernetes)为每个提交的作业启动一个集群。 该集群仅适用于该作业。 作业完成后,集群将被拆除并清除任何挥之不去的资源(文件等)。 这提供了更好的资源隔离,因为行为不端的作业只能关闭它自己的 TaskManager。 此外,它将标记的负载分散到多个 JobManager 上,因为每个作业都有一个。 由于这些原因,Per-Job 资源分配模型是许多生产原因的首选模式。
Session Mode模式
会话模式假定一个已经在运行的集群并使用该集群的资源来执行任何提交的应用程序。 在同一(会话)集群中执行的应用程序使用并因此竞争相同的资源。 这样做的好处是您不必为每个提交的作业支付启动完整集群的资源开销。 但是,如果其中一个作业行为异常或关闭了 TaskManager,那么在该 TaskManager 上运行的所有作业都将受到故障的影响。 除了对导致故障的作业产生负面影响外,这意味着潜在的大规模恢复过程,所有重新启动的作业同时访问文件系统并使其对其他服务不可用。 此外,让一个集群运行多个作业意味着 JobManager 的负载更大,JobManager 负责记录集群中的所有作业。
总结
在会话模式下,集群生命周期独立于集群上运行的任何作业的生命周期,并且资源在所有作业之间共享。 Per-Job 模式为每个提交的作业都启动了一个集群,但这带来了更好的隔离保证,因为资源不会在作业之间共享。 在这种情况下,集群的生命周期与作业的生命周期绑定。 最后,Application模式为每个应用程序创建一个会话集群,并在集群上执行应用程序的 main() 方法。
本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://lrting.top/backend/7476/