Flink架构:
分布式系统Flink,需要有效分配和管理计算资源才能执行流应用程序。它集成了所有常见的集群资源管理器,例如Hadoop Yarn,Apache Mesos,Kubernetes,但是也可以设置作为独立集群甚至库来运行。
分离模式:客户端断开连接。
附加模式:保持连接接受进程报告。
Job Manager:决策者,决定何时调度下一个task,对完成的task和执行失败作出反应,协调checkpoint,并且协调从失败中恢复的问题。(Flink中的Job Manager就类似于Spark中的Master)
1.ResourceManager:
为不同的资源调度者实现了ResourceManager(比如Yarn,Mesos,Kubernetes),资源管理者。
2.Dispatcher:提供了一个REST接口,用来提交Flink应用程序执行。为每个提交的作业启动一个JobMaster。
3.JobMaster:一个JobMaster单独管理一个JobGraph的执行,Flink集群中会有多个作业同时运行,每一个作业对应一个JobMaster。
一个集群中至少会有一个JobManager,高可用中会有多个JobManager,其中一个是Leader,其他的是StandBy,工作的JobManager如果挂掉了,立马就补上一个StandBy的JobManager。(就像是Spark中的active和standby)。
Task Manager:执行作业流,缓存和交换数据流。
Task Manager中资源调度的最小单位是task slot,Task Manager中task slot的数量代表并发处理task的数量,一个task slot可以执行多个算子。
Tasks 和 算子链:
一个task是由一个线程执行的,将算子链接成task是个有用的优化,减少了线程间的切换,缓冲等开销,并且减少延迟的同时增加整体吞吐量,链行为是可以配置的。
Task slots 和 资源:
每个worker,也就是TaskManager都是一个JVM进程,可以在单独的线程中执行一个或者多个subtask,为了控制一个TaskManager中接受多少个task,就有了所谓的task slots(至少一个)。
每个task slot代表Task Manager中资源的固定子集。例如,具有3个slot的Task Manager,会将其托管内存1/3用于每个slot。分配资源意味着subtask不会与其他作业的subtask竞争托管内存,而是具有一定数量的保留托管内存。注意此处没有CPU隔离,当前slot仅分离task的托管内存。
如果说一个Task Manager只有一个Task slot。那就证明这个task组自己独享一个JVM进程。
如果说一个Task Manager有更多的slot就意味着更多subtask共享同一个JVM进程。同一个JVM中的task共享TCP连接(通过多路复用)和心跳信息。彼此之间还可以共享数据集和数据结构,从而减少了每个task的开销。
默认情况下,Flink允许subtask共享slot,即便它们是不同的task的subtask,只要是来自于同一作业即可,结果就是一个slot可以持有整个作业管道,允许slot共享有两个主要优点:
1. Flink集群所需的task slot和作业中使用的最大并行度恰好一样(一个JVM进程中,有几个task slot就有几个线程并行工作),无需计算程序总共包含多少个task(具有不同并行度)。
2. 容易获得更好的资源利用,如果没有slot共享,非密集subtask(source/map())将阻塞和密集型subtask(window)一样多的资源。通过slot共享,基本并行度从2增加到6,可以充分利用分配的资源,同时确保繁重的subtask在Task Manager之间公平分配。
Flink应用程序执行:
Flink应用程序的作业可以被提交到长期运行的Flink Session集群,专用的Flink Job集群或者Flink Application集群中,这些选项之间的差异主要与集群的生命周期和资源隔离保证有关。
Flink Session集群:集群一直运行着,不管所有的作业完成情况,只有手动停止session。
集群生命周期:在Flink Session集群中,客户端连接到一个预先存在的,长期运行的集群,该集群可以接受多个作业提交。即使所有作业完成后,集群(和JobManager)仍将继续运行直到手动停止session为止。因此,Flink Session集群的寿命不受任何Flink作业寿命的约束。
Flink Job集群:每个提交的作业启动一个集群,作业完了,Job集群自动拆掉。
集群生命周期:在Flink Job集群中,可用的集群管理器(比如Yarn和kubernetes)用于为每个提交的作业启动一个集群,并且该集群仅可用于该作业。在这里,客户端首先从集群管理器请求资源启动JobManager,然后将作业提交给在这个进程中运行的Dispatcher。然后根据作业的资源请求惰性的分配TaskManager。一旦作业完成,Flink Job集群将被拆除。
Flink Application集群:Flink Application集群不需要启动,我们手动写好了应用程序的逻辑代码之后,打包成jar包,然后用Application集群调用就可以了(main方法),应用程序是在集群上面运行的,而不是在客户端上面运行的。
集群生命周期:Flink Application集群是专用的Flink集群,仅从Flink应用程序执行作业,并且main()方法在集群上而不是客户端上运行。提交作业是一个单步骤的过程:无需先启动Flink集群,然后将作业提交到现有的session集群;相反,将应用程序逻辑和依赖打包成一个可执行的作业jar中,并且集群入口(ApplicationClusterEntryPoint)负责调用main()方法来提取JobGraph。例如,这允许你像在Kubernetes上部署任何其他应用程序一样部署Flink应用程序。因此,Flink Application集群的寿命与Flink应用程序的寿命有关。
Flink集群类型 | 集群生命周期 | 资源隔离 | 适用场景 |
Flink Session集群 | 集群一直运行着,不管作业是否完成了,直到手动停掉session。 | slot是在提交任务的时候分配,任务完成了就释放,但是所有作业都共享一个集群,一旦其中一个TaskManager崩溃,那么TaskManager上面所有运行的task都会失败,如果JobManager出问题,那么所有正在运行的作业都完犊子了 | 有一个预先存在的集群可以节省大量时间申请资源和启动TaskManager。因为如果作业执行时间短,但是启动时间很长的话,相对于端对端来说用户体验很差。 |
Flink Job集群 | 提交一个作业就启动一个集群,作业完成了,集群自动就关掉。 | JobManager中的致命错误,只影响Flink Job集群中运行的一个作业。因为每一个作业单独在一个集群中运行,作业完成了,集群就自己停掉了。 | ResourceManager必须应用并等待外部资源管理组件来启动TaskManager进程和分配资源,所以Flink Job集群更适合长期运行,具有高稳定性要求并且对较长的启动时间不敏感的大型作业。 |
Flink Application集群 | 手动写好了作业的业务逻辑代码,打成jar包,提交作业给集群就可以了,集群会调用main()方法来提取JobGraph的。 | ResourceManager和Dispatcher作用于单个的Flink应用程序,相比较Flink Session集群来说,它提供了更好的隔离。但是和Flink Job集群来比较的话,起始Flink Job应该算是客户端运行的方案,而Flink Application算是集群方案,因为运行在集群上面。(这是和Flink Job的区别) | 这个具有和Flink Job集群相同的优点和缺点。也就是说,启动慢,但是确实比较稳定,因为一个集群只运行一个作业,作业运行完了集群自己关了。所以如果有长期的需求并且对稳定性高的,我们可以考虑这种。但是和Flink Job集群不同的地方就是,这个是运行在集群里面,而不是客户端。 |