共计 5106 个字符,预计需要花费 13 分钟才能阅读完成。
Flink 中的利用部署:以后状态与新利用模式
- 公布文章
Flink 中的利用部署:以后状态与新利用模式
同步滚动:开
作为古代企业的重要工具,流解决和实时剖析这类工具逐步衰亡,越来越多的企业以 Apache Flink 为外围构建平台,并将其作为服务在外部提供。在最新举办的 Flink Forward 会议中,Uber、Netflix 和阿里巴巴等公司的许多相干主题演讲进一步阐明了这一趋势。
泛滥平台旨在通过加重最终用户的所有经营累赘来简化外部的 Application(利用)提交。为了提交 Flink 应用程序,这些平台通常只公开一个集中式或低并行度端点(例如 Web 前端)用于利用提交,咱们将调用 Deployer(部署器)。
平台开发人员和保护人员常常提到的阻碍之一是,Deployer 可能是一个很难配置的大量资源耗费者。如果依照均匀负载进行配置,可能会导致 Deployer 服务被部署申请吞没(在最坏的状况下,短时间内对所有生产应用程序都是如此),而依照最高负载进行布局的话,又会带来不必要的老本。依据这一察看后果,Flink 1.11 引入了 Application 模式(利用模式)作为部署选项,它容许一个轻量级、更可伸缩性的利用提交过程,从而使应用程序部署负载更平均地散布在集群的各个节点上。
为了了解这个问题以及理解 Application 模式如何解决该问题,咱们首先简要概述 Flink 中应用程序执行的以后状态,而后再论述部署模式引入的架构变动以及如何利用它们。
Flink 中的应用程序执行
在 Flink 中执行应用程序次要波及三个实体:Client(客户端)、JobManager(作业管理器)和 TaskManager(工作管理器)。Client 负责将利用提交给集群,JobManager 负责执行期间必要的 bookkeeping,而 TaskManager 则负责理论的计算。更多细节请参考 Flink 的架构 文档。
以后部署模式
在 1.11 版本中引入 Application 模式之前,Flink 容许用户在 Session(会话)或 Per-Job 集群上执行应用程序。两者之间的差别与集群生命周期和它们提供的资源隔离保障无关。
Session 模式
Session 模式(会话模式)假设集群曾经运行,并应用该集群的资源来执行任何提交的应用程序。在同一(Session)集群中执行的应用程序应用雷同的资源,并因而相互竞争。这样做的益处是,你无需为每个提交的作业调配整个集群的资源开销。然而,如果其中一个作业行为不失常或者敞开了 TaskManager,那么在该 TaskManager 上运行的所有作业都将受到故障的影响。除了对导致故障的作业产生负面影响之外,这还意味着潜在的大规模复原过程,即所有重新启动的作业同时拜访文件系统,并使其不可用于其余服务。此外,单个集群运行多个作业意味着 JobManager 的负载更大,它负责集群中所有作业的 bookkeeping。这种模式非常适合启动短作业,例如交互式查问。
Per-Job 模式
在 Per-Job 模式中,可用的集群管理器框架(如 YARN 或 Kubernetes)用于为每个提交的作业启动 Flink 集群,该集群仅对该作业可用。当作业实现后,集群将敞开,并清理所有提早的资源(例如文件)。这种模式容许更好的资源隔离,因为行为不失常的作业不会影响任何其余作业。另外,因为每个应用程序都有本人的 JobManager,因而它将 bookkeeping 负载扩散到多个实体。思考到后面提到的 Session 模式中的资源隔离问题,对于长时间运行的作业,用户常常抉择 Per-Job 模式,因为这些作业违心承受肯定水平的启动提早的减少,以反对弹性。
总之,在 Session 模式中,集群生命周期独立于集群中运行的任何作业,并且集群中运行的所有作业共享其资源。Per-Job 模式抉择为每个提交的作业调配一个集群,已提供更好的资源隔离保障,因为资源不会在作业之间共享。在这种状况下,集群的生命周期与作业的生命周期相干。
Application 提交
Flink 应用程序的执行包含两个阶段:pre-flight,即当用户的 main() 办法被调用时;runtime,即用户代码调用 execute() 时立刻触发。main() 办法应用 Flink 的 API(DataStream API、Table API、DataSet API)之一结构用户程序。当 main() 办法调用 env.execute() 时,用户定义的管道将被转换成一种 Flink 运行时能够了解的模式,称为 Job Graph(作业图),并将其传递给集群。
只管它们办法有所不同,Session 模式和 Per-Job 模式都会在 Client 执行应用程序的 main() 办法,即 pre-flight 阶段。
对于曾经在本地领有作业的所有依赖项,而后通过在其机器上运行的 Client 提交其应用程序的单个用户来说,这通常不是问题。然而,对于通过近程实体(如 Deployer)提交的状况下,这个过程包含:
- 本地下载应用程序的依赖项;
- 执行 main() 办法提取 Job Graph;
- 将 Job Graph 及其依赖项发送到集群以便执行;
- 期待后果。
这使得 Client 耗费了大量的资源,因为它可能须要大量的网络带宽来下载依赖项或将二进制文件发送到集群,并且须要 CPU 周期来执行 main() 办法。随着越来越多的用户共享同一个 Client,这个问题甚至会变得更加突出。
上图展现了应用红色、蓝色和绿色示意的三个应用程序的两种部署模式。每个矩形都有三个并行项。彩色矩形示意不同的过程,别离是 TaskManager、JobManager 和 Deployer。咱们假如在所有状况下只有一个 Deployer 过程。黑白三角形示意提交过程的负载,而黑白矩形示意 TaskManager 和 JobManager 过程的负载。如图所示,Per-Job 模式和 Session 模式下的 Deployer 共享雷同的负载。它们的不同之处在于工作的调配和 JobManager 负载。在 Session 模式下,集群中的所有作业都有一个 JobManager,而在 Per-Job 模式下,每个作业都有一个 JobManager。此外,Session 模式下的工作会随机调配给 TaskManager,而在 Per-Job 模式下,每个 TaskManager 只能有单个作业工作。
Application 模式
Application 模式建设在上述察看后果的根底上,并尝试将 Per-Job 模式的资源隔离与轻量级且可伸缩的利用提交过程联合起来。为实现这一点,它为每个提交的应用程序创立一个集群,然而这一次,应用程序的 main() 办法在 JobManager 上执行。
为每个应用程序创立一个集群能够看作是创立一个只在特定应用程序的作业之间共享的 Session 集群,并在应用程序完结时敞开。应用这种架构,Application 模式提供与 Per-Job 模式雷同的资源隔离和负载平衡保障,但在整个应用程序的粒度上。这是有情理的,因为属于同一应用程序的工作应该互相关联,并被视为一个单元。
在 JobManager 上执行 main() 办法不仅能够节俭提取 Job Graph 所需的 CPU 周期,也能够节俭 Client 本地下载依赖项并将 Job Graph 及其依赖项发送到集群所需的带宽。此外,因为每个应用程序只有一个 JobManager,因而,它能够更平均地扩散网络负载。上图对此进行了阐明,其中咱们具备与“Session 和 Per-Job 部署模式”局部中雷同的场景,然而这一次 Client 负载曾经转移到了每个应用程序的 JobManager。
注:在 Application 模式下,main() 办法是在集群上执行的,而不是像在其余模式中那样在 Client 上执行。和可能对代码产生影响,例如,应用 regsiterCachedFile() 在环境中注册的任何门路都必须由应用程序的 JobManager 进行拜访。
与 Per-Job 模式相比,Application 模式容许提交由多个作业组成的应用程序。作业执行的程序不受部署模式的影响,而是受用于启动作业的调用的影响。应用阻塞 execute() 办法建设一个程序,并将导致下一个作业的执行被提早到“这个”作业实现为止。相同,一旦提交了以后作业,非阻塞 executeAsync() 办法将立刻持续提交“下一个”作业。
升高网络需要
如上所述,通过在 JobManager 上执行应用程序的 main() 办法,Application 模式能够节俭以前在提交作业时所需的大量资源。但仍有改良的余地。
重点关注 YARN,它曾经反对所有提到的 here 2,即便 Application 模式曾经就绪,Client 依然须要发送用户 Jar 到 JobManager。此外,对于每个应用程序,Client 必须将“flink-dist”目录发送到集群,该目录蕴含框架自身的二进制文件,包含 flink-dist.jar、lib/ 和 plugin/ 目录。这两者可能会在 Client 占用大量带宽。此外,在每次提交时发送雷同的 flink-dist 二进制文件既是对带宽的节约,也是对存储空间的节约。只需容许应用程序共享雷同的二进制文件即可缩小存储空间的节约。
在 Flink 1.11 中,咱们引入了医学选项,容许用户进行如下操作:
- 指定一个目录的近程门路,在该目录中,YARN 能够找到 Flink 散发二进制文件,以及
- 指定一个近程门路,YARN 能够在其中找到用户 Jar。
对于第一步,咱们利用了 YARN 的分布式缓存,并容许应用程序共享这些二进制文件。因而,如果一个应用程序碰巧在它的 TaskManager 的本地存储中找到了 Flink 的正本,因为之前的一个应用程序在同一个 TaskManager 上执行,它甚至都不须要在外部下载它。
注:这两种优化都能够用于 YARN 上的所有部署模式,而不仅仅是 Application 模式。
示例:YARN 上的 Application 模式
无关残缺阐明,请参阅 Flink 的官网文档,更具体地说,请参阅援用集群治理框架的页面,例如 YARN 或 Kubernetes。接下来我将给出一些对于 YARN 的例子,其中上述所有性能都是可用的。
要以 Application 模式启动用用程序,能够应用:
./bin/flink run-application -t yarn-application ./MyApplication.jar
应用这条命令,所有的配置参数,例如用于疏导应用程序状态的保留点的门路,或者所需的 JobManager/TaskManager 内存大小,都能够通过它们的配置选项(以 -d 作为前缀)来指定。无关可用配置选项的目录,请参阅 Flink 的 配置页面。
例如,指定 JobManager 和 TaskManager 内存大小的命令如下所示:
./bin/flink run-application -t yarn-application \
-Djobmanager.memory.process.size=2048m \
-Dtaskmanager.memory.process.size=4096m \
./MyApplication.jar
最初,为了进一步节俭提交应用程序 Jar 所需的带宽,能够事后将其上传到 HDFS,并指定指向 ./MyApplication.jar 的近程门路,如下所示:
./bin/flink run-application -t yarn-application \
-Djobmanager.memory.process.size=2048m \
-Dtaskmanager.memory.process.size=4096m \
-Dyarn.provided.lib.dirs="hdfs://myhdfs/remote-flink-dist-dir" \
hdfs://myhdfs/jars/MyApplication.jar
这将使作业提交变得更加轻量级,因为所需的 Flink jar 和应用程序 Jar 将从指定的近程地位提取,而不是由 Client 发送到集群。Client 将惟一提供给集群的是应用程序的配置,其中包含上述提到的所有门路。
总结
咱们心愿本文的探讨可能帮忙你了解 Flink 提供的各种部署模式之间的差别,并且可能帮忙你作出理智的决定,到底哪一种模式适宜你本人的设置。
作者介绍:
Kostas Kloudas,Apache Flink PMC Member、Committer,Ververica 软件工程师。
原文链接:
https://flink.apache.org/news/2020/07/14/application-mode.html