Flink集群架构
Flink集群是由一个JobManager和多个TaskManager组成的:Client用来提交任务给JobManager,JobManager分发任务给TaskManager去执行,然后TaskManager会以心跳的方式汇报任务状态。从架构图去看,JobManager很像Hadoop中的JobTracker,TaskManager也很像Hadoop中的TaskTracker。
1 Job Client
JobClient不是Flink程序执行的内部部分,它是任务执行的起点。主要职责如下:
提交任务, 提交后可以结束进程, 也可以等待结果返回;
负责接受用户的程序代码,然后创建数据流,将数据流提交给JobManager以便进一步执行;
执行完成后,Job Client将结果返回给用户。
2 JobManager
JobManager是主进程(也称为作业管理器)协调和管理程序的执行。JobManager决定何时调度下一个task、对完成的task或执行失败做出反应、协调checkpoint、并且协调从失败中恢复等等。在整个集群中至少有一个Master,负责调度task,协调checkpoints和容灾。如果是高可用架构可以设置多个Master,但是只有一个是Leader,其它是standby。
JobManager进程由三个不同的组件组成:
ResourceManager:负责Flink集群中的资源提供、回收、分配。它管理task slots,这是 Flink集群中资源调度的单位。Flink为不同的环境和资源提供者(例如YARN、Kubernetes 和standalone部署)实现了对应的ResourceManager。在standalone设置中,ResourceManager只能分配可用TaskManager的slots,而不能自行启动新的TaskManager。
Dispatcher:Dispatcher 提供了一个 REST 接口,用来提交Flink应用程序执行,并为每个提交的作业启动一个新的JobMaster。它还运行Flink WebUI用来提供作业执行信息。
JobMaster:负责管理单个JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的JobMaster。
3 TaskManager
TaskManager从JobManager处接收需要部署的Task,并部署和启动任务, 接收上游的数据并处理,是实际负责执行计算的节点。
集群中至少有一个TaskManager。一般一个Flink作业是分布在多个TaskManager上执行的,单个TaskManager上提供一定的slot
TaskManager是在JVM中的一个或多个线程中执行任务的工作节点。TaskManager启动后,相关的slot信息会被注册到ResourceManager中。当某个作业提交后,ResourceManager会将空闲的Slot提供给JobManager,JobManager再将这些空闲的slot资源进行分配
任务执行的并行性由每个TaskManager上可用的Task Slots决定。每个任务代表分配TaskSlot的一组资源。例如,如果TaskManager有四个插槽,那么它将为每个插槽分配 25%的内存
4 TaskSlot
TaskSlot即任务槽,是TaskManager中资源调度的最小单位,task slot的数量表示并发处理task的数量。类似YARN当中的Container,用于资源的封装,但是在Flink中,taskSlot只负责封装内存的资源,不包含CPU的资源。
每一个TaskManager中会包含3个TaskSlot,所以每一个TaskManager中最多能并发执行的任务是可控的,最多3个
TaskSlot有独占的内存资源,在一个TaskManager中可以运行不同的任务
一个 task slot 中可以执行多个算子
Task Slot当中的 Task 就是任务执行的具体单元
默认情况下,Flink 允许子任务共享Slot,即使它们是不同task的subtask,只要它们来自相同的 job。这种共享可以有更好的资源利用率。
5 Flink工作流程
Flink基本工作流程如上图所示:
用户编写应用程序代码,并通过Client客户端提交作业
JobClient将作业提交给JobManager
JobManager返回Client端作业提交成功
JobManager在接收到作业后会向ResourceManager申请本次作业所需的资源,将作业中的逻辑视图转换为物理执行图,然后将计算任务分发部署到多个TaskManager上
TaskManager接收到任务请求后,会启动一个线程开始执行。执行过程中,TaskManager会继续向JobManager报告作业执行的状态,比如开始执行、正在进行或已完成。
作业执行完成后,结果将发送回客户端(JobClient)
Task Slots和Resource
每个 worker(TaskManager)都是一个 JVM 进程,可以在单独的线程中执行一个或多个 subtask。为了控制一个TaskManager中接受多少个task,就有了所谓的 task slots(至少一个)。
每个task slot代表TaskManager中资源的固定子集。例如,具有3个slot的TaskManager,会将其托管内存均分1/3用于每个slot。资源分配后意味着subtask不会与其他作业的subtask竞争托管内存,仅使用已经分配的资源。注意slot没有CPU隔离,只是针对内存进行了分配。
通过调整task slot的数量,用户可以定义subtask如何互相隔离。如果Task slot数量为1,意味着每个task组都在单独的 JVM 中运行;如果有多个Task slots则意味着更多subtask共享同一JVM。同一JVM中的task共享TCP连接(通过多路复用)和心跳信息。它们还可以共享数据集和数据结构,从而减少了每个task的开销。
默认情况下,Flink允许subtask共享slot,即便它们是不同的task的subtask,只要是来自于同一作业即可。结果就是一个slot可以持有整个作业管道。允许slot共享有两个主要优点:
Flink集群所需的task slot和作业中使用的最大并行度恰好一样。无需计算程序中总共包含多少个task。
容易获得更好的资源利用。如果没有slot共享,非密集subtask(source/map())将阻塞和密集型subtask(window)一样多的资源。通过slot共享,如下图所示并行度从2增加到6,可以充分利用分配的资源,同时确保繁重的subtask在TaskManager之间公平分配。
分布式分发
jobmanager 和 taskmanager
main方法只在jobmanager执行,在taskmanager不会执行
main绘制完流程图后,会把执行的slot分发出去(到各个机器,通过网络)
通过网络分发后的程序会丢失部分信息 内存里的信息都会丢失,需要重新set (刷到内存里面)
但是类里面的初始化后的非transient属性是会被序列化并带到分发的机器里的。
所以get是在main执行的时候getprofile,变成类的属性,被带到分布式机器集群里
在分发出去的机器上,不set直接get会null,因为main没有执行
而且算子分发顺序不可控
为了保证一定可以获取到配置,需要每个类都set
configutil应该都是空的
task里的profile属性,在JobManager里初始化后已经有值了,所以分发到taskmanager里就没丢
Q:flink taskmanager运行main函数吗?
A:在Flink中,TaskManager并不直接运行应用程序的
main
函数。相反,Flink应用程序的执行是由Flink的执行引擎负责的。
当你提交一个Flink应用程序时,Flink会将应用程序打包成一个可执行的JAR文件,并将其提交给Flink集群的JobManager。JobManager负责接收和调度应用程序,并将任务分配给TaskManager执行。
每个TaskManager都会启动一个或多个任务插槽(slot),每个插槽可以执行一个或多个子任务。当JobManager将任务分配给TaskManager时,TaskManager会根据任务的并行度和资源配置,在其插槽上加载应用程序的代码和依赖项,并执行任务。
因此,Flink的执行过程是由Flink的执行引擎负责的,而不是直接运行应用程序的
main
函数。
main
函数只是应用程序的入口点,用于启动Flink应用程序的执行。实际的任务执行是由Flink的执行引擎在TaskManager上完成的。
Q:当JobManager将任务分配给TaskManager时,可执行的JAR文件也全部传给TaskManager了吗
在Flink中,当JobManager将任务分配给TaskManager时,并不会将整个可执行的JAR文件传递给TaskManager。相反,Flink使用分布式文件系统(如HDFS)或其他远程文件系统来共享应用程序的可执行代码和依赖项。
A:在提交Flink应用程序时,你需要将应用程序的可执行JAR文件上传到分布式文件系统中,例如HDFS。然后,Flink会将应用程序的位置信息和依赖项信息发送给TaskManager。TaskManager会根据这些信息从分布式文件系统中获取应用程序的代码和依赖项,并在其插槽上加载和执行任务。
这种方式可以确保应用程序的可执行代码和依赖项在整个集群中共享和复用,而不需要将整个JAR文件传递给每个TaskManager。
需要注意的是,Flink还提供了一种可选的方式,即将应用程序的代码和依赖项打包到每个任务的本地文件系统中。这种方式称为"Blob"模式,它可以提高任务的启动速度和执行性能。但是,这种方式会增加每个TaskManager的存储开销,并且不适用于大型应用程序。
综上所述,Flink并不会将整个可执行的JAR文件传递给TaskManager,而是使用分布式文件系统来共享应用程序的代码和依赖项。
版权归原作者 新叶猿 所有, 如有侵权,请联系我们删除。