Flink 的执行图(Execution Graph)
Apache Flink 的 ExecutionGraph(执行图) 是 Flink 作业调度和执行的核心数据结构。它是 Flink 作业生命周期中从逻辑视图向物理执行视图转换的关键一步。
简单来说,ExecutionGraph 是 JobGraph 的并行化版本。它包含了所有并行执行的任务实例(Subtasks)以及它们之间的数据传输通道。
以下是关于 Flink ExecutionGraph 的详细解析:
1. Flink 的图转换流程(上下文)
为了理解 ExecutionGraph,首先需要知道它在 Flink 图转换流程中的位置。Flink 作业提交后,会经历以下四个阶段的图转换:
- StreamGraph (流图): 根据用户代码(API 调用)生成的最初始的拓扑图。节点是 Operator(算子)。
- JobGraph (作业图): (在 Client 端或 JobManager 端生成) 对 StreamGraph 进行优化,将多个符合条件的 Operator 融合(Chain)成一个 Operator Chain。这是提交给 JobManager 的最终逻辑视图。
- ExecutionGraph (执行图): (在 JobManager 端生成) 根据 JobGraph 和用户设置的并行度(Parallelism)生成的图。它是调度的核心依据。
- Physical Graph (物理执行图): 具体的 Task 在 TaskManager 上部署并运行的物理视图。
2. 什么是 ExecutionGraph?
ExecutionGraph 存在于 JobManager 中。当 JobManager 接收到 JobGraph 后,会根据配置的并行度,将 JobGraph 中的每一个逻辑节点(JobVertex)拆分成多个物理执行节点(ExecutionVertex)。
核心特点:
- 并行化: 它是 JobGraph 的并行化展开。如果一个算子的并行度是 10,那么在 ExecutionGraph 中就会有 10 个对应的执行顶点。
- 调度依据: Scheduler(调度器)根据 ExecutionGraph 来决定将哪些 Task 部署到哪些 TaskManager 的 Slot 上。
- 状态追踪: 它负责追踪每个并行子任务(Subtask)的运行状态(Created, Scheduled, Deploying, Running, Finished, Failed 等)。
3. ExecutionGraph 的内部结构
ExecutionGraph 是一个复杂的对象,主要由以下核心组件构成:
A. ExecutionJobVertex (逻辑节点容器)
- 对应 JobGraph 中的一个
JobVertex。 - 它是一个逻辑容器,汇总了该算子所有并行子任务的信息。
- 例如:一个并行度为 4 的
Map算子,对应一个ExecutionJobVertex。
B. ExecutionVertex (物理执行节点)
- 这是
ExecutionJobVertex内部的具体实例。 - 数量 = 并行度。如果并行度是 4,那么
ExecutionJobVertex内部包含 4 个ExecutionVertex数组 (task[0]到task[3])。 - 每个
ExecutionVertex代表一个具体的 Subtask(子任务),最终会被调度到一个 TaskManager 的 Slot 中运行。
C. IntermediateResult (中间结果集)
- 对应 JobGraph 中的
IntermediateDataSet。 - 表示一个算子产生的逻辑输出数据集。
D. IntermediateResultPartition (中间结果分区)
- 对应
IntermediateResult的物理分区。 - 数量 = 并行度。
- 每个
ExecutionVertex都会生产一个或多个IntermediateResultPartition。下游的ExecutionVertex通过读取这些分区来获取数据。
E. ExecutionEdge (执行边)
- 连接上游的
IntermediateResultPartition和下游的ExecutionVertex。 - 它定义了数据如何流转(例如:Hash Shuffle, Rebalance, Forward 等)。
4. 举例说明:从 JobGraph 到 ExecutionGraph
假设我们有一个简单的 Flink 任务:Source (并行度=2) -> map (并行度=2) -> keyBy -> sink (并行度=2)
JobGraph 视角:
- 节点 A: Source + Map (Operator Chain)
- 节点 B: Sink
- 连接: A -> B (通过 Hash 方式)
ExecutionGraph 视角:
JobManager 会根据并行度将其展开:
ExecutionJobVertex A (Source+Map)
- 包含
ExecutionVertex A_0(Subtask 1) - 包含
ExecutionVertex A_1(Subtask 2) - 产出
Partition A_0和Partition A_1
- 包含
ExecutionJobVertex B (Sink)
- 包含
ExecutionVertex B_0(Subtask 1) - 包含
ExecutionVertex B_1(Subtask 2)
- 包含
连接 (Edges)
- 由于是
keyBy(Hash Shuffle),数据会发生交换。 Partition A_0会连接到ExecutionVertex B_0和B_1。Partition A_1也会连接到ExecutionVertex B_0和B_1。- 这形成了一个全连接(All-to-All)的网络结构。
- 由于是
5. ExecutionGraph 的作用
ExecutionGraph 在 Flink 运行时扮演着指挥官的角色:
作业调度 (Scheduling):
调度器(如 DefaultScheduler)遍历 ExecutionGraph 的顶点,根据依赖关系(上游是否产出数据)决定何时调度下游任务,并向 ResourceManager 申请 Slot。故障恢复 (Failover):
当某个 Task 失败时,ExecutionGraph 会感知到。根据配置的重启策略(Restart Strategy),它决定是重启单个受影响的 Region,还是重启整个作业。Checkpoint 协调:
Checkpoint Coordinator 通过 ExecutionGraph 找到所有的 Source 节点,触发 Checkpoint Barrier 的注入,并跟踪所有 Subtask 的 Checkpoint 确认状态。背压与数据流监控:
虽然实际数据流经 TaskManager,但 ExecutionGraph 维护了分区的元数据,用于监控数据流转的拓扑结构。
总结
ExecutionGraph 是 Flink 物理执行层的蓝图。
- 输入: JobGraph + 并行度。
- 输出: 具体的 Task 部署动作。
- 本质: 将逻辑的算子链(Operator Chains)拆解为实际可运行的并行子任务(Subtasks)及其互联网络。