一、Flink Graph(DAG)
在Flink中的执行图可以分成四层:StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图。
- StreamGraph:是根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的拓扑结构。
- JobGraph:StreamGraph经过优化后生成了 JobGraph,提交给 JobManager 的数据结构。主要的优化为,将多个符合条件的节点 chain 在一起作为一个节点,这样可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗。
- ExecutionGraph:JobManager 根据 JobGraph 生成ExecutionGraph。ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构。
- 物理执行图:JobManager 根据 ExecutionGraph 对 Job 进行调度后,在各个TaskManager 上部署 Task 后形成的“图”,并不是一个具体的数据结构。
二、Flink job
- Job:作业,类似Storm中的Topology,同样对应着Flink中的一层层的图,从StreamGraph --> JobGraph --> ExecutionGraph --> 物理执行图。
- Task:类似于Storm中的Bolt,为了拓扑更高效地运行,Flink提出了Chaining,尽可能地将operators chain在一起作为一个task来处理。对应于JobGraph中的JobVertex。
- operator:算子,对应于StreamGraph中的StreamNode。
三、Operator chains
1、概述
- 所谓的Operator chains,存在于Flink中StreamGraph --> JobGraph的过程中,将多个符合条件的StreamNode节点 chain在一起作为一个JobNode节点的优化行为.(StreamNode就是Operator,因此称为Operator chains)
2、为什么Operator chains
- 为了更高效地分布式执行,Flink会尽可能地将operator的subtask链接(chain)在一起形成task。每个task在一个线程中执行。将operators链接成task是非常有效的优化:它能减少线程之间的切换,减少消息的序列化/反序列化,减少数据在缓冲区的交换,减少了延迟的同时提高整体的吞吐量。
3、可以进行Operator chains的条件
- 1、上下游的并行度一致
- 2、下游节点的入度为1 (也就是说下游节点没有来自其他节点的输入)
- 3、上下游节点都在同一个 slot group 中(下面会解释 slot group)
- 4、下游节点的 chain 策略为 ALWAYS(可以与上下游链接,map、flatmap、filter等默认是ALWAYS)
- 5、上游节点的 chain 策略为 ALWAYS 或 HEAD(只能与下游链接,不能与上游链接,Source默认是HEAD)
- 6、两个节点间数据分区方式是 forward(参考理解数据流的分区)
- 7、用户没有禁用 chain
四、Task Slot
1、概述
- Flink 中的计算资源通过 Task Slot 来定义。每个 task slot 代表了 TaskManager 的一个固定大小的资源子集。例如,一个拥有3个slot的 TaskManager,会将其管理的内存平均分成三分分给各个 slot。将资源 slot 化意味着来自不同job的task不会为了内存而竞争,而是每个task都拥有一定数量的内存储备。需要注意的是,这里不会涉及到CPU的隔离,slot目前仅仅用来隔离task的内存。
2、共享Slot:SlotSharingGroup
- 概述:
- 所谓的共享Slot,就是指:不同operator下面的subTask(这里是说,一个operator往往会因为并行度的原因,被分解成并行度个数的Task,并行执行),可以在同一个Task Slot中运行,即共享Slot。
- 在Storm中,supervisor下面是work,work中往往一个Executor执行一个Task。
- 而在Flink中,TaskManager下面是slot,相同的是Slot和Work都是一个JVM进程,不同的是TaskManager会对Slot进行资源分配。
- 优点:
- Flink 集群所需的task slots数与job中最高的并行度一致。也就是说我们不需要再去计算一个程序总共会起多少个task了。
- 更容易获得更充分的资源利用。如果没有slot共享,那么非密集型操作source/flatmap就会占用同密集型操作 keyAggregation/sink 一样多的资源。如果有slot共享,将基线的2个并行度增加到6个,能充分利用slot资源,同时保证每个TaskManager能平均分配到重的subtasks。