目录
一 运行架构
(一) JobManager
(二) ResourceManager
(三)Dispatcher
(四)JobMaster
(五)TaskManager
二 核心概念
(一) TaskManager与Slots
(二) Parallelism(并行度)
(三) Task与SubTask
(四) 任务链Operator Chains
三 yarn-cluster提交流程 per-job
Flink运行时最少需要一个JobManager和至少1个TaskManager.
其中,JobManager控制一个应用程序执行的主进程.
首先,JobManager接收要执行的应用程序(作业图/类/库/JAR包等),将作业图转为物理层面的数据流图(执行图),执行图包括了所有的并发可执行任务,之后JobManager会向资源管理器(ResourceManager)请求执行任务必要的资源,也就是任务管理器(TaskManager)上的插槽(slot)。一旦它获取到了足够的资源,就会将执行图分发到真正运行它们的TaskManager上。
同时,在运行过程中,JobManager会负责所有需要中央协调的操作,比如说检查点(checkpoints)的协调。
也就是说,JobManager主要作用:
1 接收客户端任务
2 划分具体执行任务
3 申请资源
负责资源的管理,在整个 Flink 集群中只有一个 ResourceManager. 注意这个ResourceManager不是Yarn中的ResourceManager, 是Flink中内置的, 只是赶巧重名了而已.
主要负责管理任务管理器(TaskManager)的插槽(slot)
当JobManager申请插槽资源时,ResourceManager会将有空闲插槽的TaskManager分配给JobManager。如果ResourceManager没有足够的插槽来满足JobManager的请求,它还可以向资源提供平台发起会话,以提供启动TaskManager进程的容器。另外,ResourceManager还负责终止空闲的TaskManager,释放计算资源。
负责接收用户提供的作业,并且负责为这个新提交的作业启动一个新的JobMaster 组件. Dispatcher也会启动一个Web UI,用来方便地展示和监控作业执行的信息。
JobMaster负责管理单个JobGraph的执行. 每个Job都有一个自己的JobMaster.
Flink中每一个worker(TaskManager)都是一个JVM进程,它可能会在独立的线程上执行一个Task。为了控制一个worker能接收多少个task,worker通过Task Slot来进行控制(一个worker至少有一个Task Slot)
每个task slot表示TaskManager拥有资源的一个固定大小的子集。假如一个TaskManager有三个slot,那么它会将其管理的内存均分成三份给各个slot。资源slot化意味着一个task将不需要跟来自其他job的task竞争被管理的内存,取而代之的是它将拥有一定数量的内存储备。需要注意的是,这里不会涉及到CPU的隔离,slot目前仅仅用来隔离task的受管理的内存。
总结:slot会均分内存资源,进而达到内存隔离,相互之间不会占用内存。但cpu资源不会隔离,可以共享cpu资源。
一个特定算子的子任务(subtask)的个数被称之为这个算子的并行度(parallelism).
一般情况下,一个流程序的并行度,可以认为就是其所有算子中最大的并行度。示例如果map是4个并行度,flatmap是3个,那么流程序的并行度为4.
一个程序中,不同的算子可能具有不同的并行度,如果是yarn模式会动态申请资源slot个数小于并行度那么程序将会卡死一直处于create状态,等待足够资源,才运行,如果是standalone模式,不会动态申请资源,slot个数小于并行度那么程序将会直接失败。
并行度优先级 : 算子指定>env全局指定>提交参数>配置文件
谁的粒度更细,谁的优先级越高
不同算子的子任务(SubTask)经过一定的优化,串在一起,形成一个新的SubTask对TaskManager来讲,就是一个Task。
Stream在算子之间传输数据的形式可以是one-to-one(forwarding)的模式也可以是redistributing的模式,具体是哪一种形式,取决于算子的种类.
redistribute过程就类似于Spark中的shuffle过程,即:每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务。
例如,keyBy()基于hashCode重分区、broadcast和rebalance会随机重新分区,这些算子都会引起redistribute过程
相同并行度的one to one操作,Flink将这样相连的算子链接在一起形成一个task,原来的算子成为里面的一部分。 每个task被一个线程执行.
将算子链接成task的优化特点:
减少线程之间的切换和基于缓存区的数据交换,在减少时延的同时提升吞吐量
指定编程API:
算子.startNewChain() =>与前面都断开
算子.disableChaining() => 与前后都断开
env.disableOperatorChaining() => 全局都不串
断开操作链的好处在于减少某个slot的压力
共享组
默认只有一个共享组,设置共享组后,slot的使用个数并不仅仅是与程序中最大算子的并行度有关了,当算子设置共享组后会使用额外的slot来执行.
在一个job内,默认情况下只有一个共享组,此时slot个数等于流程序的并行度 ; 在有多个共享组的情况下,slot个数每个共享组中最大算子并行度之和
.slotSharingGroup("group1")
0 Flink任务提交后,Client向HDFS上传Flink的Jar包和配置
1 向Yarn ResourceManager提交任务,ResourceManager分配Container资源
2 通知对应的NodeManager启动ApplicationMaster,ApplicationMaster启动后加载Flink的Jar包和配置构建环境,然后启动JobManager(Dispatcher)
2.1 Dispatcher启动JobMaster
3 JobMaster向ResourceManager(Flink)申请资源
4 ResourceManager(Flink)向ResourceManager(Yarn)申请资源启动TaskManager
5 ResourceManager分配Container资源后,由ApplicationMaster通知资源所在节点的NodeManager启动TaskManager
6 TaskManager注册Slot
7 发出提供Slot命令
8 TaskManager向JobMaster提供Slot
9 JobMaster提交要在Slot中执行的任务