文章目录
- 前言
- 一、整体架构概览
- [二、JobManager --- 集群的"大脑"](#二、JobManager — 集群的“大脑”)
-
- [2.1 定义与职责](#2.1 定义与职责)
- [2.2 核心职责](#2.2 核心职责)
- [2.3 内部组件](#2.3 内部组件)
- [2.4 代码示例:提交作业到JobManager](#2.4 代码示例:提交作业到JobManager)
- [三、TaskManager --- 真正的"执行者"](#三、TaskManager — 真正的“执行者”)
-
- [3.1 定义与职责](#3.1 定义与职责)
- [3.2 核心职责](#3.2 核心职责)
- [3.3 Slot --- 资源的最小单位](#3.3 Slot — 资源的最小单位)
- [3.4 TaskManager配置示例](#3.4 TaskManager配置示例)
- [四、Job --- 用户提交的"作业"](#四、Job — 用户提交的“作业”)
-
- [4.1 定义](#4.1 定义)
- [4.2 从代码到执行](#4.2 从代码到执行)
- [4.3 Job的并行度](#4.3 Job的并行度)
- [五、Task --- 最小的执行单元](#五、Task — 最小的执行单元)
-
- [5.1 定义](#5.1 定义)
- [5.2 Subtask与并行度](#5.2 Subtask与并行度)
- [5.3 算子链(Operator Chain)](#5.3 算子链(Operator Chain))
- 六、四者关系图解
- 七、常见面试题
- 八、总结
前言
在学习和使用Apache Flink的过程中,很多初学者常常会被几个核心概念搞混:Task 、Job 、TaskManager 、JobManager。它们之间到底是什么关系?各自扮演什么角色?今天这篇文章就来彻底讲清楚这四个Flink中的核心概念。
一、整体架构概览
首先,让我们从Flink的运行时架构说起。一个Flink集群通常遵循**主从架构(Master-Worker)**模式:
- Master角色:JobManager
- Worker角色:TaskManager
而Job和Task则是运行在这套架构上的逻辑单元。
简单来说:
- JobManager 管"调度"
- TaskManager 干"苦力"
- Job 是"任务单"
- Task 是"具体活"
下面我们逐一深入分析。
二、JobManager --- 集群的"大脑"
2.1 定义与职责
JobManager 是整个Flink集群的控制中心,负责协调和管理分布式任务的执行。每个Flink集群至少有一个JobManager(高可用模式下可以有多个,通过Leader选举确定主节点)。
2.2 核心职责
| 职责 | 说明 |
|---|---|
| 作业管理 | 接收用户提交的Job,生成执行计划(ExecutionGraph) |
| 资源管理 | 向TaskManager分配slot,协调资源 |
| 任务调度 | 将ExecutionGraph中的任务分发给TaskManager执行 |
| Checkpoint协调 | 触发和管理分布式Checkpoint(容错机制核心) |
| 故障恢复 | 检测Task失败并重新调度 |
2.3 内部组件
JobManager内部主要包含三个重要组件:
- ResourceManager:负责管理TaskManager的slot资源
- Dispatcher:提供REST接口接收作业提交,启动JobMaster
- JobMaster:负责单个作业的执行管理(每个作业对应一个JobMaster)
2.4 代码示例:提交作业到JobManager
java
// 创建Flink环境(连接到JobManager)
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 定义数据处理逻辑
DataStream<String> text = env.socketTextStream("localhost", 9999);
DataStream<Long> counts = text.flatMap((line, out) -> {
for (String word : line.split(" ")) {
out.collect(word);
}
}).returns(String.class)
.map(word -> 1L)
.keyBy(value -> value.f0)
.sum(1);
// 提交作业到JobManager执行
counts.print();
env.execute("My Flink Job");
三、TaskManager --- 真正的"执行者"
3.1 定义与职责
TaskManager 是Flink集群中的工作节点,真正执行计算任务的Worker进程。每个TaskManager是一个独立的JVM进程,负责管理自己内部的资源(以Slot为单位)并执行具体任务。
3.2 核心职责
| 职责 | 说明 |
|---|---|
| 任务执行 | 执行JobManager分配给它的Task |
| 数据交换 | 负责不同Task之间的网络数据传输(Shuffle) |
| 内存管理 | 管理托管内存(Managed Memory),用于排序、缓存等 |
| 心跳上报 | 定期向JobManager发送心跳,报告状态和资源使用情况 |
| Checkpoint执行 | 参与状态快照的创建与存储 |
3.3 Slot --- 资源的最小单位
每个TaskManager内部会划分出多个Task Slot,这是Flink中资源分配的最小单位。
TaskManager JVM
┌─────────────────────────────────────┐
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Slot 1 │ │ Slot 2 │ │ Slot 3 │ │
│ │ Task A │ │ Task B │ │ Task C │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────┘
Slot的特点:
- 一个Slot可以运行一个任务的并行子任务(Subtask)
- 同一个TaskManager中的Slot共享JVM资源(内存、TCP连接等)
- 默认情况下,同一个TaskManager的不同Slot之间是隔离的,但可以复用网络连接
3.4 TaskManager配置示例
yaml
# flink-conf.yaml 配置
taskmanager.numberOfTaskSlots: 4 # 每个TaskManager的slot数量
taskmanager.memory.process.size: 2048m # TaskManager进程总内存
taskmanager.memory.managed.size: 512m # 托管内存大小
taskmanager.memory.network.min: 128m # 网络缓冲区最小内存
四、Job --- 用户提交的"作业"
4.1 定义
Job 是用户通过Flink API编写的一个完整的数据处理应用程序。它包含了数据源(Source)、数据转换(Transformation)、数据输出(Sink)的完整拓扑结构。
4.2 从代码到执行
一个Job的生命周期如下:
用户代码 → StreamGraph → JobGraph → ExecutionGraph → 物理执行
| 阶段 | 说明 |
|---|---|
| StreamGraph | 根据代码生成的初始逻辑执行计划(包含算子) |
| JobGraph | 经过优化(如算子链合并)后的逻辑执行计划 |
| ExecutionGraph | JobManager将JobGraph并行化后的物理执行计划 |
| 物理执行 | TaskManager执行具体的Subtask |
4.3 Job的并行度
一个Job可以被拆分为多个并行的Subtask,并行度(Parallelism)决定了Subtask的数量。
java
// 设置全局并行度
env.setParallelism(4);
// 为特定算子设置并行度
dataStream.map(x -> x * 2).setParallelism(8);
五、Task --- 最小的执行单元
5.1 定义
Task 是Flink中最小的执行单元。当JobManager将Job提交给TaskManager执行时,Job会被拆分成多个Task,每个Task在TaskManager的Slot中独立运行。
5.2 Subtask与并行度
每个Task实际上是Job中某个算子的一个并行子任务(Subtask)。
Job (Parallelism = 3)
┌─────────────────────────────────────────┐
│ Source Task │
│ ├── Subtask 1 (Slot 1) │
│ ├── Subtask 2 (Slot 2) │
│ └── Subtask 3 (Slot 3) │
│ │
│ Map Task │
│ ├── Subtask 1 (Slot 1) │
│ ├── Subtask 2 (Slot 2) │
│ └── Subtask 3 (Slot 3) │
└─────────────────────────────────────────┘
5.3 算子链(Operator Chain)
为了优化性能,Flink会将多个算子合并成一个Task,这称为算子链。合并的条件是:
- 上下游并行度相同
- 是一对一(One-to-One)的数据传输模式
java
// 禁用算子链(用于调试或特殊场景)
dataStream.map(x -> x * 2).disableChaining();
// 开启新链
dataStream.map(x -> x * 2).startNewChain();
六、四者关系图解
下面这张图清晰地展示了四者之间的关系:
┌─────────────────────────────────────────────────────────────────┐
│ Flink Cluster │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ JobManager │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │JobMaster│ │Resource │ │Dispat- │ │ │
│ │ │ │ │Manager │ │atcher │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ ↑ ↑ ↑ │ │
│ │ │ 调度Job │ 管理Slot │ 接收提交 │ │
│ └───────┼────────────┼────────────┼──────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ TaskManager │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Slot 1 │ │ Slot 2 │ │ Slot 3 │ │ │
│ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │
│ │ │ │ SubTask │ │ │ │ SubTask │ │ │ │ SubTask │ │ │ │
│ │ │ │ (Task) │ │ │ │ (Task) │ │ │ │ (Task) │ │ │ │
│ │ │ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Job (逻辑层面)
┌─────────────────────┐
│ Source → Map → Sink │
└─────────────────────┘
关系总结表
| 概念 | 类型 | 层级 | 生命周期 | 举例 |
|---|---|---|---|---|
| JobManager | 进程 | 集群主节点 | 随集群启动 | 1个集群有1~N个 |
| TaskManager | 进程 | 集群工作节点 | 随集群启动 | 1个集群有M个 |
| Job | 逻辑单元 | 应用层 | 提交→完成 | 每个作业1个 |
| Task | 执行单元 | 物理层 | 作业执行期间 | 1个Job有K个 |
七、常见面试题
Q1:JobManager挂了怎么办?
A:如果开启了高可用(HA)模式,Flink会使用ZooKeeper进行Leader选举,备用JobManager会自动接管。作业可以从最近的Checkpoint恢复。如果没有HA,作业会失败。
Q2:TaskManager和Slot的关系是什么?
A:一个TaskManager是一个JVM进程,包含多个Slot。Slot是资源分配的最小单位,每个Slot可以运行一个Subtask。Slot之间共享JVM资源,但任务执行是隔离的。
Q3:一个TaskManager宕机会有什么影响?
A:该TaskManager上运行的所有Subtask会失败。JobManager会检测到心跳超时,然后根据Checkpoint将这些Subtask重新调度到其他可用的TaskManager上执行。
Q4:并行度大于Slot总数会怎样?
A:如果作业的并行度大于所有TaskManager的Slot总数,作业会处于等待状态,直到有足够的Slot资源可用。
八、总结
| 组件 | 一句话总结 |
|---|---|
| JobManager | 集群的"大脑",负责调度和协调 |
| TaskManager | 集群的"手脚",负责真正执行计算 |
| Job | 用户提交的"作业蓝图",描述数据处理逻辑 |
| Task | 执行的最小单元,是Job并行化后的实际工作负载 |
理解这四个核心概念,是掌握Flink架构设计的基石。希望这篇文章能帮助你理清它们之间的关系,在实际开发和调优中更加得心应手。
如需获取更多关于 Flink流处理核心机制、状态管理与容错、实时数仓架构 等深度解析,请持续关注本专栏《Flink核心技术深度与实践》系列文章。