文章

Flink 工作流程剖析

Flink 工作流程剖析

Apache Flink 是一个分布式流计算框架,支持高吞吐、低延迟、状态管理,并具备批流一体的特性。


Flink 作业从代码编写到实际运行的完整流程如下:

  1. 用户编写 Flink 作业代码
  2. Flink 编译作业并生成 JobGraph
  3. JobManager 解析 JobGraph,生成 ExecutionGraph
  4. TaskManager 分配 Slot 并执行任务
  5. 数据流转,触发 Checkpoint 机制,维护状态
  6. 作业完成或失败后进行资源释放

下图展示了 Flink 执行流程:

  ┌───────────────────────────────────────────────┐
  │          用户提交 Flink 作业(main)          │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │        Client 解析代码,生成 JobGraph         │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │  JobManager 接收 JobGraph,转换成 ExecutionGraph  │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │  JobManager 请求 TaskManager 分配 TaskSlot    │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │        TaskManager 运行 Task 处理数据         │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │       触发 Checkpoint 进行状态快照存储        │
  └───────────────────────────────────────────────┘
                        │
                        ▼
  ┌───────────────────────────────────────────────┐
  │ 作业完成(成功 / 失败),释放资源,记录结果  │
  └───────────────────────────────────────────────┘

2. 详细执行流程剖析

2.1 用户提交作业

用户通过 DataStream API / Table API / SQL 编写 Flink 任务,并调用 env.execute("Job Name") 提交任务。

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<String> stream = env.fromElements("Hello", "Flink");
stream.print();
env.execute("Flink Job");

此时,Flink Client 负责:

  • 解析用户代码,构造 JobGraph
  • 提交 JobGraph 到 JobManager 进行调度

2.2 JobGraph 解析

JobGraph 是 Flink 作业的逻辑执行计划,由 StreamGraph 转换而来,包含:

  • Vertices(节点):代表算子(Source、Map、Reduce、Sink)
  • Edges(边):表示数据流的依赖关系
Source → Map → KeyBy → Window → Sink

示例:

env.fromElements(1, 2, 3)
    .map(value -> value * 2)
    .print();

对应的 JobGraph

(Source) → (Map) → (Sink)

2.3 ExecutionGraph 生成

JobManager 接收 JobGraph,转换成 ExecutionGraph,它是 Flink 内部用于调度执行的 物理执行计划。

ExecutionGraph 由多个 ExecutionVertex 组成,每个 ExecutionVertex 对应 Task 的一个并行子任务。

示例: 假设 JobGraph 任务有 Map → KeyBy → Reduce,如果 Map 并行度=2,Reduce 并行度=1:

[ExecutionGraph]
   ├── (Task1-1, Task1-2)  [Map]
   └── (Task2-1)           [Reduce]

2.4 任务调度

TaskManager(TM) 是 Flink 的计算节点,JobManager(JM) 负责为 ExecutionGraph 任务分配 TaskSlot 进行调度:

  1. JobManager 请求 TaskManager 提供资源
  2. TaskManager 返回可用 Slot
  3. JobManager 将 ExecutionVertex 映射到 TaskSlot
  4. 任务启动并运行

Flink 使用 Slot Sharing(槽共享),多个算子可以共享一个 TaskSlot,提高资源利用率。


2.5 Task 执行 & 数据流

Task 是 Flink 执行单元,Task 运行后:

  1. Source 读取数据
  2. 算子(Operators)执行计算
  3. 通过 Network Shuffle 传输数据
  4. Sink 输出数据

数据流可以是:

  • 批处理(Batch):有界数据,数据处理完后作业终止
  • 流处理(Streaming):无界数据,作业持续运行

示例:

DataStream<String> stream = env.fromElements("A", "B", "C")
    .map(value -> value.toLowerCase());

此时,Flink 任务流:

Source(A, B, C) → Map(a, b, c) → Sink

2.6 Checkpoint & State 维护

Flink 采用 异步 Checkpoint 机制保证数据一致性:

  1. Source 生成 Barrier(屏障)
  2. Barrier 随数据流传播
  3. 各 Task 保存状态到 StateBackend
  4. 当所有 Task 确认 Checkpoint 完成,作业状态存入持久化存储(如 HDFS、RocksDB)

示例:

env.enableCheckpointing(5000);  // 5 秒触发一次 Checkpoint

2.7 作业完成 / 失败

  • 正常完成:Flink 释放资源,关闭作业
  • 失败重启:
    • 失败恢复(RestartStrategy):
      • 固定间隔重启
      • 失败次数限制
      • 无限重启
    • 状态恢复(StateBackend):
      • 通过 Checkpoint 进行状态恢复

示例:

env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, Time.seconds(10)));

3. 总结

Flink 任务执行的完整流程:

  1. 用户代码提交
  2. Client 生成 JobGraph
  3. JobManager 解析 JobGraph,构建 ExecutionGraph
  4. TaskManager 分配 Slot 并启动任务
  5. 数据流动 & 状态管理
  6. Checkpoint 保障容错
  7. 作业完成 / 失败重启
License:  CC BY 4.0