目录
运行架构
客户端
JobManager(作业管理器)
ResourceManager(资源管理器)
TaskManager(任务管理器)
Dispatcher(分发器)
flink on yarn 提交任务执行流程
TaskManager与Slots
什么是slot
程序与数据流(DataFlow)
执行图(ExecutionGraph)
并行度(Parallelism)
任务链(Operator Chains)
运行架构
Flink运行时由两种类型的进程组成: JobManager和一个或多个TaskManager
客户端
客户端不是运行时和程序执行的一部分,但它用于准备并发送dataflow(JobGraph)给Master(JobManager),然后,客户端断开连接 (detached mode)或者维持连接 (attached mode)以等待接收计算结果。客户端既可以作为触发执行的Java / Scala程序的一部分运行,也可以在命令行进程中运行
./bin/flink run ...
JobManager(作业管理器)
控制一个应用程序执的主进程,也就是说,每个应用程序都会被一个不同的JobManager所控制执行。
1.JobManager会接收要执行的应用程序,这个应用程序会包括: 作业图(JobGraph)、逻辑数据流图(logical dataflow graph)和打包了所有的类、库和其他资源的JAR包。
2.JobManagr会把JobGraph转换成一个物理层面的数据流图,这个图被叫做“执行图”(ExecutionGraph),包含了所有可以并发执行的任务。
3.JobManager会向资源管理器(ResourceManager)请求执行任务必要的资源,也就是任务管理器(TaskManager)上的slot。
4.一旦获取足够的资源,就会将执行图分发到真正运行它们的TaskManager上。
5.运行过程中,JobManager负责中央协调工作、例如协调对故障恢复
ResourceManager(资源管理器)
1.主要负责taskManager的slot
2.flink为不同的环境和资源管理工具提供了不同资源管理器,比如Yarn、Mesos、k8s以及standalone部署
3.当Jobmanager申请插槽资源时,ResourceManager会将空闲插槽的TakManager分配给JobManager
TaskManager(任务管理器)
1.flink包含多个TaskManager,每个TaskManager中都包含了一定数量的slots
2.TaskManager会向资源管理器注册它的slot
3.收到资源管理器的指令后,TaskManager就会将一个或者多个slot供给JobManager调用,JobManager就可以向slot分配tasks来执行了
4.taskManager可以跟它运行同一应用程序的taskManager交换数据
Dispatcher(分发器)
它为应用提交提供了REST接口
但一个应用被提交执行时,分发器就会启动并将应用提交给一个JobManager
Dispather在架构中可能不是必须的,这取决于提交运行的方式
最上面的运行时架构有些复杂,下面是任务提交流程简化图
flink on yarn 提交任务执行流程
1.flink提交任务后,Client向hdfs上传flink的jar包和配置
2.向yarn resourceManager提交任务,ResourceManager分配Container资源
3.RM通知NodeManager启动AM,AM启动后加载hdfs上flink的jar包和配置构建环境,然后启动jobManager
4.AM向RM申请资源启动TaskManager
5.RM分配Container资源后,由AM通知资源所在节点的NodeManager启动TaskManager
6.NodeManager加载Flink的jar包和配置构建环境并启动TaskManager
7.TaskManager启动后向JobManager发送心跳包,并等待JobManager向其分配任务
TaskManager与Slots
- Flink有多个worker(TaskManager),每个woker进程中可执行一个或多个subtask。woker通过 task slot来进行控制
- 每个task slot表示 TaskManager拥有资源的固定大小,如果一个taskmanager有三个slot,那么内存分成三份给slot
- 资源slot化意味着一个subtask将不需要跟来自其他job的subtask竞争被管理的内存,取而代之的是它将拥有一定量的内存。
- 不是CPU隔离,slot目前仅仅用来隔离task的受管理的内存
- 通过调整任务槽的数量,用户可以定义子任务如何相互隔离。每个TaskManager具有一个插槽,意味着每个任务组都在单独的JVM中运行(例如,可以在单独的容器中启动)。具有多个插槽意味着更多子任务共享同一JVM。同一JVM中的任务共享TCP连接(通过多路复用)和心跳消息。他们还可以共享数据集和数据结构,从而减少每个任务的开销。
什么是slot
flink的每一个application都会根据前后的算子操作划分为一个个Task(就好比spark的stage),每一个Task里面封装了一个个 sub-task (就好比spark的 Taskset里面封装了一个个task),这些sub-task就是一个个并行的实例(线程),那么线程运行的资源在哪呢?flink集群为每个TaskManager提供了solt(资源槽)。 solt的数量通常与每个TaskManager节点的可用CPU内核数成比例。一般情况下你的slot数是你每个节点的cpu的核数。我们的sub-task就是运行在这个slot资源槽内的,如下图
- 默认情况下,Flink允许子任务共享slot,即使它们是不同任务的子任务(前提是它们来自同一个job)。 这样的结果是,一个slot可以保存作业的整个管道。
Task Slot是静态的概念,是指TaskManager具有的并发执行能力,可以通过参数taskmanager.numberOfTaskSlots进行配置;而并行度parallelism是动态概念,即TaskManager运行程序时实际使用的并发能力,可以通过参数parallelism.default进行配置。
也就是说,假设一共有3个TaskManager,每一个TaskManager中的分配3个TaskSlot,也就是每个TaskManager可以接收3个task,一共9个TaskSlot,如果我们设置parallelism.default=1,即运行程序默认的并行度为1,9个TaskSlot只用了1个,有8个空闲,因此,设置合适的并行度才能提高效率。
程序与数据流(DataFlow)
- 在运行时,Flink上运行的程序会被映射成dataflow
执行图(ExecutionGraph)
- Flink中的执行图可以分成四层: StreamGraph->JobGraph->ExecutionGraph->物理执行图
- StreamGraph:用户通过Stream AP编写的代码生成的最初的图 client上生成
- JobGraph:StreamGraph经过优化后生成了JobGraph,提交给JobManager,将符合条件的节点chain合并,这样可以减少数据在节点之间流动所需要的序列化/反序列化传输消耗 ,是调度层最核心的数据结构 client上生成
- ExecutionGraph:是JobGraph的并行版本 jobmanager上执行
- 物理执行图: JobManager 根据 ExecutionGraph 对 Job 进行调度后,在各个TaskManager 上部署 Task 后形成的“图”,并不是一个具体的数据结构 task上运行
并行度(Parallelism)
一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)
任务链(Operator Chains)
- 相同并行度的one to one操作,Flink这样相连的算子链接在一起形成一个task,原来的算子成为里面的一部分