学习笔记如下:
上图展示了 Flink 集群的各个构建(building blocks)。通常来说:
可选的外部组件:
一旦作业到达了全局结束的状态(包括完成、失败和被取消),与作业关联的外部组件资源将被清理。在资源清理失败时,Flink 将会重试清理,重试策略可以配置。
当资源清理达到最大重试次数,但还没有成功时,其组件需要手动清理。重新启动相同作业(根据 job ID 判断)将导致资源清理重新开始,而不会再次运行作业。
Flink 有以下三种应用执行模式:
以上模式的差异包括:
main()
方法在客户端执行还是在集群执行在其他所有模式下,应用程序的 main()
方法都是在客户端执行。这就要求在本地下载应用程序的依赖项,执行 main()
以提取 Flink 可以理解的应用程序标识形式(即 JobGraph),并将依赖项和 JobGraph
发送给集群。此时,客户端需要大量的网络带宽来下载依赖项并将二进制文件发送给集群,同时需要 CPU 来执行 main()
,使得客户端成了资源的重度消耗者。当客户端在用户之间共享时,这个问题会更加明显。
出于这个考虑,Application Mode 为每个提交的应用创建一个集群,但是应用程序的 main()
方法由 JobManager 来执行。为每个应用程序创建一个集群,可以被视为在特定应用程序的作业之间创建了一个会话集群(session cluster),并在应用程序完成时拆除。通过这种架构,Application Mode 提供了与 Per-Job Mode 相同的资源隔离和负载均衡保证,但是是在整个应用程序的粒度上。在 JobManager 上执行 main()
方法,可以节省 CPU 资源,还可以节省本地下载依赖项所需的带宽。此外,因为每个应用程序都有一个 JobManager,所以还可以支持更均匀的分布式网络负载,以便在集群中下载应用程序的依赖项,
在应用程序模式下,main()
在集群上执行,而不是在其他模式下在客户端上执行。这将对代码逻辑产生影响,例如,在环境中使用 registerCachedFile()
注册的任何路径都必须能够被应用程序的 JobManager 访问。
相较于 Per-Job Mode,Application Mode 允许提交由多个 Job 组成的应用程序。作业执行的顺序不受部署模式的影响,但受到作业启动的调用的影响。使用阻塞的 execute()
方法,这将导致下一个任务直到当前任务完成后才会执行;使用非阻塞的 executeAsync()
,将导致下一个任务在当前任务完成前就会开始。
Application Mode 允许应用程序中包含多个 execute()
,但是在这种情况下不支持高可用。Application Mode 的高可用性仅支持包含单个 execute()
的应用程序。
此外,当 Application Mode 下运行的多个 Job 中的任何一个被取消,则会导致所有 Job 都被停止并且 JobManager 将会关闭。支持通过关闭数据源完成 Job。
为了提供更好的资源隔离保证,Per-Job Mode 使用资源提供者框架(例如 YARN、Kubernetes)为每个提交的作业启动一个集群。该集群仅用于该作业。当作业完成时,这个集群会被拆除,任何残留的资源(例如文件等)都将被清除。这提供了更好的资源隔离,因为一个行为错误(misbehaving)的 Job 只能导致自己的 TaskManagers 被关闭。
此外,它通过让每个 Job 都有一个 JobManager,分散了 book-keeping 的压力。
Session Mode 假设已经有一个集群正在运行,并使用该集群的资源来执行任何提交的应用程序。所有的应用程序都在同一个集群上运行,并因此竞争相同的资源。
优势:不需要为每个提交的作业支付启动完整集群的资源开销
劣势:
在 Session Mode 中,集群的生命周期独立于集群上的任何作业,资源在所有作业之间共享。
在 Per-Job Mode 中,需要为每个 Job 支付启动集群的资源,但是有更好的资源隔离,因为资源不会在作业之间共享。在这种情况下,集群的生命周期和 Job 的生命周期绑定在一起。
在 Application Mode 中,会为每个应用程序创建一个 Session Cluster 并在集群上执行应用程序的 main()
方法。