天天看点

Flink-02 核心架构

  1. Flink运行架构

Flink 是一个分布式系统,需要有效分配和管理计算资源才能执行流应用程序。它集成了所有常见的集群资源管理器,例如Hadoop YARN、Apache Mesos和Kubernetes,但也可以设置作为独立集群甚至库运行。

Flink-02 核心架构
    1. 客户端:

 Client 不是运行时和程序执行的一部分,而是用于准备数据流并将其发送给 JobManager。之后,客户端可以断开连接(分离模式),或保持连接来接收进程报告(附加模式)。客户端可以作为触发执行 Java/Scala 程序的一部分运行,也可以在命令行进程./bin/flink run ...中运行。

可以通过多种方式启动 JobManager 和 TaskManager:直接在机器上作为standalone 集群启动、在容器中启动、或者通过YARN或Mesos等资源框架管理并启动。TaskManager 连接到 JobManagers,宣布自己可用,并被分配工作。

Client其实就是将用户的代码执行逻辑进行拆分形成执行图,将执行图发送给JobManager来进行支配运行。就像是Spark的Submit程序但是比Submit又多了一些任务拆解的部分,Spark的执行DAG是在Driver端划分的。

    1. JobManager:

JobManager是一个独立的JVM进程其中包含了诸多功能

4.2.1 ResourceManager:

这个ResourceManager是一个资源协调的组件,主要用于资源提供、回收、分配-管理task slots。Flink可以运行在不同的资源调度框架上例如Yarn、mesos、K8s或standalone上面,这里ResourceManager分别做了不同的实现。

4.2.2 Dispatcher:

提供了一个Rest接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。(其实这个组件在Yarn上以cluster方式运行的时候没啥用,standalone模式用处更大)

4.2.3 JobMaster:

JobMaster负责管理单个Job的执行图的执行,集群中有多个Job就是多个JobMaster来分别管理执行。(yarn cluster方式其实一个小集群就一个任务也就一个JobMaster,standalone模式集群中会有多个JobMaster)

    1. TaskManager:

TaskManager其实就是干活的,负责将jobmaster划分下来的task执行,TaskManager执行的最小单位就是task slot。Slot的数据量就决定了task的并发量,一个task slot里面是可以执行多个算子的。

    1. Task和operator chains

Task和操作链之间的关系

Flink-02 核心架构

实际上如果不考虑算子合并的问题,一个Flink job的task数量可以理解为source的数量  + 算子数量  +  sink数量 。在这里官网给出的解释是一个subtask是使用一个线程来执行的。这样这个任务使用了多少个线程来执行job就很清晰了,但是考虑到优化的问题task之间是可以合并的,比如上图中的Source和map算子并行度一致进行合并处理那么source 和map就形成了一个operator chains操作链被放到了一个task中执行(考虑并行度就是task下面并行度个SubTask)。这样的好处就是可以减少数据从线程到下个线程的切换缓冲甚至网络IO的开销。

在上图中有一个很重要的东西叫SubTask,这个很重要,下图还会用到。

    1. Slot和Resource
Flink-02 核心架构

Slot槽位和resource资源之间的关系。这个槽位Slot这个东西是这样产生的,我有一个TaskManager来执行task,那么我这个TaskManager可以执行多少个task呢,我这样做将TaskManager的内存划分为若干份,其中一份我给它定义为Slot槽位,TaskManager能执行多少个task取决于TaskManager有多少个槽位slot,这就是Slot和TaskManager资源之间的关系。他们之间是用内存来划分的,而不是cpu核心数。

这里的slot并不是核心数,和spark执行任务的core是不一样的,在Spark中core的数量可以决定最高并行度,实现中是将按照core的数量初始化线程池基于线程是cpu调度的最小单元的理论默认表示该节点最大并行度是分配的core的数量,并不严谨。

以下是官方解释:

每个 worker (TaskManager) 是一个JVM 进程,可以在单独的线程中执行一个或多个子任务。为了控制 TaskManager 接受多少任务,它有所谓的任务槽(至少一个)。

每个任务槽代表 TaskManager 资源的一个固定子集。例如,具有三个插槽的 TaskManager 会将其托管内存的 1/3 专用于每个插槽。分配资源意味着子任务不会与来自其他作业的子任务竞争托管内存,而是拥有一定数量的保留托管内存。请注意,这里没有发生 CPU 隔离;当前插槽仅分隔任务的托管内存。

通过调整任务槽的数量,用户可以定义子任务如何相互隔离。每个 TaskManager 有一个插槽意味着每个任务组都在单独的 JVM 中运行(例如,可以在单独的容器中启动)。拥有多个插槽意味着更多的子任务共享同一个 JVM。同一 JVM 中的任务共享 TCP 连接(通过多路复用)和心跳消息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。

Flink-02 核心架构

默认情况下,Flink 允许 subtask 共享 slot,即便它们是不同的 task 的 subtask,只要是来自于同一作业即可。结果就是一个 slot 可以持有整个作业管道。允许 slot 共享有两个主要优点:

  1. Flink 集群所需的 task slot 和作业中使用的最大并行度恰好一样。无需计算程序总共包含多少个 task(具有不同并行度)。
  2. 容易获得更好的资源利用。如果没有 slot 共享,非密集 subtask(source/map())将阻塞和密集型 subtask(window) 一样多的资源。通过 slot 共享,我们示例中的基本并行度从 2 增加到 6,可以充分利用分配的资源,同时确保繁重的 subtask 在 TaskManager 之间公平分配。

上图中一个TaskSlot中包含的是一个数据流的流向过程,是几个Task的subtask组成的,source/map --> keyBy/Window/appply --> Sink这是组成了一个任务链细分到并行度上就是一组subtask组成的任务链,Flink默认情况下是会这样安排的,这样安排会带来几个好处,上面片段已经做出介绍。

    1. 并行度Parallelism

在4.4中提到了task的subtask,其实subtask有几个取决于它有设置了几个并行度。

Flink-02 核心架构

这张图的下半部分就是介绍并行度的,其中Source是数据源,可以几个source同时读取数据源,这就是source的并行度。Source到map然后map到下游,这里只画了两个map当然也可以是多个map其实就是将map的并行度给定多个(这个source和map都是两个将来就有可能将source和map划分到一个operator chains操作链中得到优化),这里有个注意的点就是从上游算子到下游算子数据的下发策略有几种,可以是一对一下发,也可以是根据key下发(有点像map-reduce计算的shuffle过程)。

  1. 一对一下发

上游一个分区的数据下发只能下发到下游的同一个一个分区里,这种方式就是一对一下发有点像spark中的宽依赖的概念。

  1. 重新分发下发

重新分发是有多种重新分发的策略的,可以是随机的重新分发、根据key进行分发、broadcast广播分发,有点像spark中的窄依赖的概念。

    1. 执行图ExecutionGraph
Flink-02 核心架构
  1. StreamGraph

流图就是根据用户的代码直接生成的数据流图,就是一个程序算子节点的拓扑图。

StreamNode:就是一个DataStream类的实现,该节点是如何计算的及顶点的入度出度相关信息。

StreamEdge:边属性描述的是上游算子对下游算子数据传输相关的属性比如数据分发方式,及边带有的form/to的描述信息。

  1. JobGraph

从StreamGraph到JobGraph做的就是operator chain的优化,也就是能合并的task给合并到一个operator chain操作链中了。

  1. ExecutionGraph

执行图可以看做是JobGraph的并行版,也就是从并行的角度拆分了JobGraph。

  1. PhysicalGraph

物理的执行图就是将拆分好的ExecutionGraph所描述出来的节点划分到各个TaskManager上运行的结构。

继续阅读