news 2026/10/20 18:12:36

Flink 2.3.0 从理论到实践 —— 第 2 章 Flink 运行时架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flink 2.3.0 从理论到实践 —— 第 2 章 Flink 运行时架构

Flink 2.3.0 从理论到实践 —— 第 2 章 Flink 运行时架构

课程定位:本章深入 Flink 2.3.0 的内部运作机制,理解 JobManager / TaskManager 的协作、作业从提交到执行的完整链路、Task / SubTask / Slot 的资源模型,以及 Flink 2.x 引入的自适应调度与可插拔运行时。掌握架构是后续调优与排错的基础。

版本基线:Flink 2.3.0 + JDK 17


章节导读

  • 2.1 架构总览:两层进程模型
  • 2.2 核心组件详解
  • 2.3 作业执行链路:从提交到物理执行
  • 2.4 任务与资源模型
  • 2.5 执行模式:流 / 批 / 自动
  • 2.6 高可用(HA)
  • 2.7 Flink 2.x 架构演进
  • 2.8 本章小结与下章预告

2.1 架构总览:两层进程模型

Flink 采用两层进程模型:一个JobManager集群(控制面)+ 多个TaskManager(数据面)。

┌──────────────────────────────────────────────────────────────────────┐ │ Flink 集群架构 │ └──────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────┐ │ JobManager(控制面) │ │ ┌───────────┐ ┌────────────┐ ┌───────────────┐ ┌───────────┐ │ │ │Dispatcher│ │JobMaster │ │ResourceManager│ │Web UI/REST│ │ │ │接收作业 │ │协调单个作业 │ │管理TM/资源 │ │监控入口 │ │ │ └───────────┘ └────────────┘ └───────────────┘ └───────────┘ │ └───────────────────────────────┬──────────────────────────────────┘ │ 心跳 + 任务调度 ┌───────────────────────┼───────────────────────┐ ▼ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ TaskManager 1 │ │ TaskManager 2 │ │ TaskManager N │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │ Slot 1 │ │ │ │ Slot 1 │ │ │ │ Slot 1 │ │ │ │ Slot 2 │ │ │ │ Slot 2 │ │ │ │ Slot 2 │ │ │ │ ... │ │ │ │ ... │ │ │ │ ... │ │ │ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │ │ 本地状态+网络 │ │ 本地状态+网络 │ │ 本地状态+网络 │ └───────────────┘ └───────────────┘ └───────────────┘

两个核心原则:

原则说明
JM 无状态(逻辑上),TM 有状态(物理上)JM 负责调度与元数据,TM 承载数据计算与本地状态
JM 与 TM 解耦JM 故障不影响正在运行的 TM 计算(可从 Checkpoint 恢复)

2.2 核心组件详解

2.2.1 JobManager(JM)

JobManager 是 Flink 集群的控制面,负责作业的接收、调度、协调与监控。它内部包含以下组件:

组件职责
Dispatcher接收客户端提交的作业,启动 JobMaster,提供 REST API 与 Web UI
JobMaster每个作业一个 JobMaster,负责该作业的调度、Checkpoint 协调、故障恢复
ResourceManager管理 TaskManager 的注册与资源分配,处理 Slot 请求与回收
Web UI / REST提供作业监控、集群状态、历史查询等可视化入口

关键点:JobMaster 是每作业一个,不是全局一个。多个作业共享同一个 JobManager 进程,但各自有独立的 JobMaster。

2.2.2 TaskManager(TM)

TaskManager 是 Flink 集群的数据面(Worker 进程),负责执行具体的计算任务。

组件职责
Task SlotTM 的资源单位,一个 Slot 对应一组计算资源(CPU + 内存切片)
Task / SubTask实际运行在 Slot 中的计算线程
Network BufferTM 间数据传输的缓冲区,基于 Netty
State Backend本地状态存储(HashMap / ForSt)

Flink 2.x 变化:TM 的内存模型在 2.x 中进一步细化,引入了更精细的托管内存(Managed Memory)划分,用于状态、网络缓冲、批处理等。

2.2.3 客户端(Client)

客户端不是集群的一部分,负责:

  • 将用户程序编译成JobGraph
  • 通过 Dispatcher 提交到集群
  • 接收作业执行结果(可选)
用户代码 → Client 编译 → JobGraph → Dispatcher → JobMaster → 调度到 TM

2.3 作业执行链路:从提交到物理执行

一个 Flink 作业从用户提交到实际执行,要经历四层图结构的转化。

2.3.1 四层图结构

用户代码(StreamGraph) │ Client 编译 + 优化 ▼ JobGraph(可提交的作业图) │ JobMaster 生成 ▼ ExecutionGraph(并行执行图) │ 调度器部署 ▼ 物理执行(Task 在 TM 的 Slot 中运行)
阶段产物生成者说明
1. StreamGraph流图Client用户 API 调用生成的最初 DAG,算子间以边连接
2. JobGraph作业图Client 优化算子链化(Operator Chain)+ 中间结果分区策略,可提交
3. ExecutionGraph执行图JobMasterJobGraph 的并行化版本,每个算子展开为并行实例
4. 物理执行Task调度器ExecutionGraph 部署到 TM 的 Slot 中,实际运行

2.3.2 算子链化(Operator Chain)

为了减少线程切换与网络开销,Flink 会把能链在一起的算子合并成一个 Task,在同一个线程中执行。

未链化(3 个 Task,3 次线程切换): Source → Map → Filter → Sink 链化后(1 个 Task,0 次线程切换): [Source → Map → Filter → Sink] ← 同一个线程

算子链化的条件(必须同时满足):

条件说明
上下游并行度相同并行度不同无法链化
上下游在同一个 Slot Sharing Group默认都在default组
数据转发策略为 Forward即forward分区,非rebalance/keyBy
没有禁用链化未调用disableChaining()
上下游算子数量未超限受chain.length限制

实践:算子链化是 Flink 性能优化的重要手段。但在某些场景(如需要独立监控某个算子)下,可以通过disableChaining()或slotSharingGroup()手动拆分。

2.3.3 调度过程

JobMaster 中的Scheduler负责将 ExecutionGraph 中的 Task 调度到 TM 的 Slot 中:

JobMaster(Scheduler) │ 1. 请求 Slot ▼ ResourceManager │ 2. 分配 TM + Slot ▼ TaskManager │ 3. 启动 Task 线程 ▼ Task 在 Slot 中运行

2.4 任务与资源模型

这是 Flink 中最容易混淆的概念。我们用一个具体例子来说明。

2.4.1 核心概念定义

概念定义
Operator(算子)用户定义的计算逻辑单元,如map、keyBy、window
Task算子链化后的物理执行单元,一个 Task 包含一个或多个算子
SubTaskTask 的并行实例,Task 有并行度 N 就有 N 个 SubTask
SlotTaskManager 的资源单位,一个 Slot 可以运行多个 SubTask(不同 Task 的)
Parallelism(并行度)一个算子/Task 的并行实例数量

2.4.2 关系图解

假设一个作业有 3 个算子(Source、Map、Sink),并行度为 2,且能链化为一个 Task:

TaskManager(2 个 Slot) ┌────────────────────────────────────┐ │ Slot 0 │ Slot 1 │ │ ┌────────────┐ │ ┌────────────┐ │ │ │ SubTask 0 │ │ │ SubTask 1 │ │ │ │ [Source-0] │ │ │ [Source-1] │ │ │ │ [Map-0] │ │ │ [Map-1] │ │ │ │ [Sink-0] │ │ │ [Sink-1] │ │ │ └────────────┘ │ └────────────┘ │ └────────────────────────────────────┘ Task 数 = 1(链化后) SubTask 数 = 2(并行度) Slot 数 = 2(每个 SubTask 占 1 个 Slot)

2.4.3 Slot Sharing(槽共享)

Slot Sharing是 Flink 的关键设计:同一个作业的不同 Task 的 SubTask 可以共享同一个 Slot。

假设 3 个 Task(A、B、C),并行度 2,2 个 Slot: Slot 0 Slot 1 ┌──────────────┐ ┌──────────────┐ │ A-SubTask-0 │ │ A-SubTask-1 │ │ B-SubTask-0 │ │ B-SubTask-1 │ │ C-SubTask-0 │ │ C-SubTask-1 │ └──────────────┘ └──────────────┘ 3 个 Task × 2 并行度 = 6 个 SubTask 共享到 2 个 Slot 中(每个 Slot 跑 3 个 SubTask)

Slot Sharing 的好处:

好处说明
资源利用率高轻算子和重算子共享 Slot,避免轻算子占着 Slot 不干活
Slot 数 = 最大并行度只需保证 Slot 数 ≥ 作业的最大并行度即可
负载均衡每个 Slot 运行完整的算子管线,负载更均匀

Slot Sharing Group:

  • 默认所有算子在default组,可共享
  • 可通过slotSharingGroup("name")为算子指定组,不同组之间不能共享
  • 常用于隔离重型算子(如大状态的 Join)到独立 Slot

结论:作业所需的最少 Slot 数 = 所有 Slot Sharing Group 中的最大并行度。

2.4.4 并行度的来源与优先级

并行度的设置有四个来源,按优先级从高到低:

优先级 1: 算子级 .setParallelism(n) ← 最高 优先级 2: 环境级 env.setParallelism(n) 优先级 3: 客户端命令 -p n / flink run -p n 优先级 4: 集群默认 parallelism.default ← 最低

注意(来自实测经验):Flink SQL 中SET 'table.exec.default-parallelism' = 'n'设置的是 Table API 的默认并行度,它与 DataStream 的env.setParallelism()是两套机制。Kafka Source 的并行度由 Kafka 分区数决定,不受table.exec.default-parallelism控制。

2.4.5 资源配置示例

假设一个 TM 配置taskmanager.numberOfTaskSlots: 4,taskmanager.memory.process.size: 8g:

配置项值说明
taskmanager.numberOfTaskSlots4每个 TM 4 个 Slot
taskmanager.memory.process.size8gTM 总内存(含 JVM、托管、网络)
taskmanager.memory.task.heap.size~3gTask 堆内存
taskmanager.memory.managed.size~4g托管内存(状态、批处理)

Slot 与内存的关系:Slot 不独占内存,内存是 TM 级别共享的。Slot 主要是线程调度与资源隔离的逻辑单位,不是严格的内存隔离。


2.5 执行模式:流 / 批 / 自动

Flink 2.x 支持三种执行模式,通过execution.runtime-mode配置。

2.5.1 三种模式对比

模式execution.runtime-mode特点适用场景
流模式streaming持续运行,处理无界流实时计算
批模式batch处理有界数据,跑完即退出离线 ETL
自动模式automatic根据 Source 是否有界自动选择流批一体

2.5.2 流模式 vs 批模式的执行差异

流模式(streaming): Source ──► Map ──► KeyBy ──► Window ──► Sink (持续运行, 数据逐条流动, 增量计算) 批模式(batch): Source ──► Map ──► Shuffle ──► Reduce ──► Sink (阶段执行, 上一阶段完成后才开始下一阶段, 全量计算)
维度流模式批模式
数据流动逐条流式按阶段(Stage)批量
Shuffle 策略Pipeline(流水线)Blocking(阻塞)
状态持续维护,Checkpoint 快照阶段结束即释放
容错Checkpoint 恢复重算整个阶段
调度所有 Task 同时调度按阶段依次调度
内存状态 + 网络缓冲排序、哈希表

2.5.3 自动模式

Source 有界? ──是──► batch 模式 │ 否 ▼ streaming 模式

适用:同一套 SQL 既能跑实时又能跑离线时使用。例如SELECT * FROM kafka_table(流)vsSELECT * FROM hive_table(批),设为automatic即可自动切换。


2.6 高可用(HA)

生产环境中,JobManager 的单点故障会导致整个集群不可用。Flink 通过Standby JobManager实现高可用。

2.6.1 HA 架构

┌────────────────────────────────────────────────────────────┐ │ ZooKeeper / Kubernetes │ │ (用于 Leader 选举 + 元数据持久化) │ └──────────────────┬─────────────────────┬───────────────────┘ │ │ ┌────────▼────────┐ ┌────────▼────────┐ │ JobManager │ │ JobManager │ │ (Leader) │ │ (Standby) │ └─────────────────┘ └─────────────────┘ │ ┌────────▼───────────────┐ │ TaskManager 集群 │ └─────────────────────────┘

2.6.2 HA 机制

机制说明
Leader 选举多个 JM 竞争,选出一个 Leader,其余 Standby
元数据持久化JobGraph、Checkpoint 元数据存到 ZooKeeper/K8s + 持久化存储
故障切换Leader 故障时,Standby 接管,从持久化存储恢复作业

2.6.3 两种 HA 方案

方案依赖适用场景
ZooKeeper HAZooKeeper 集群YARN / Standalone 部署
Kubernetes HAK8s API ServerKubernetes 部署

Flink 2.x 趋势:Kubernetes HA 方案逐渐成为主流,不依赖外部 ZooKeeper,运维更简单。


2.7 Flink 2.x 架构演进

Flink 2.0 对运行时架构做了重大重构,引入了两个关键能力。

2.7.1 Adaptive Scheduler(自适应调度器)

传统调度器在作业启动时静态分配并行度与 Slot,运行中无法调整。Adaptive Scheduler 支持运行时动态调整:

维度传统调度器Adaptive Scheduler
并行度启动时固定可运行时增减
Slot 分配静态动态申请/释放
扩缩容需重启在线调整
资源利用按峰值规划按需弹性
传统: 3 TM × 4 Slot = 12 Slot 全部预占 自适应: 闲时 2 TM × 2 Slot = 4 Slot,忙时自动扩到 12 Slot

2.7.2 Pluggable Runtime(可插拔运行时)

Flink 2.x 将运行时抽象为可插拔接口,允许接入不同的执行引擎:

Flink API / SQL 层 │ ▼ ┌─────────────────────────────────┐ │ Pluggable Runtime Interface │ ├──────────────┬──────────────────┤ │ 传统执行引擎 │ 其他执行引擎 │ │ (Stream/Batch)│ (如 Flink-1.x │ │ │ 兼容模式等) │ └──────────────┴──────────────────┘

意义:为 Flink 未来支持多种执行后端(如自研引擎、异构计算)打下基础,是架构层的长期投资。

2.7.3 其他 2.x 架构变化

变化说明
ForSt 状态后端RocksDB 的替代实现,性能更优,2.x 默认推荐
内存模型细化托管内存划分更精细,支持状态、网络、批处理独立配置
网络栈优化基于 Netty 的网络栈升级,提升 TM 间吞吐

2.8 本章小结与下章预告

本章小结

┌────────────────────────────────────────────────────────────────┐ │ 第 2 章 要点回顾 │ └────────────────────────────────────────────────────────────────┘ ✓ 两层进程模型: JobManager(控制面) + TaskManager(数据面) JM 内部: Dispatcher / JobMaster / ResourceManager / Web UI ✓ 作业四层图: StreamGraph → JobGraph(算子链化) → ExecutionGraph(并行化) → 物理执行 算子链化条件: 同并行度 + 同 Slot Group + forward + 未禁用 ✓ 资源模型: Operator → Task(链化后) → SubTask(并行实例) → Slot(资源单位) Slot Sharing: 同作业不同 Task 的 SubTask 可共享 Slot 最少 Slot 数 = 最大 Slot Sharing Group 的并行度 ✓ 并行度优先级: 算子级 > 环境级 > 客户端命令 > 集群默认 Kafka Source 并行度 = Kafka 分区数 ✓ 执行模式: streaming(持续) / batch(阶段) / automatic(自动判断) ✓ 高可用: ZooKeeper HA / Kubernetes HA Leader 选举 + 元数据持久化 + Standby 接管 ✓ Flink 2.x: Adaptive Scheduler(在线扩缩容) Pluggable Runtime(可插拔执行引擎) ForSt 状态后端(替代 RocksDB)

下章预告

第 3 章 环境准备与集群部署:动手搭建 Flink 2.3.0 运行环境。涵盖 JDK 17 与依赖准备、本地模式安装、Standalone 集群、YARN 三种模式(Session / Per-Job / Application)、Kubernetes Operator 部署、flink-conf.yaml核心配置参数、Web UI 与 REST API 基础使用。

官方参考资料

  • Flink 架构官方文档:https://nightlies.apache.org/flink/flink-docs-stable/docs/concepts/flink-architecture/
  • Task Slot 与资源:https://nightlies.apache.org/flink/flink-docs-stable/docs/concepts/flink-architecture/#task-slots-and-resources
  • 执行模式:https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/execution_mode/
  • 高可用配置:https://nightlies.apache.org/flink/flink-docs-stable/docs/deployment/ha/overview/
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 18:34:27

page_alloc __rmqueue_smallest

__rmqueue_smallest() 是伙伴系统分配路径的核心函数,负责从指定迁移类型的空闲链表中,找到最接近请求阶数的页块并分配出去。核心作用它实现了伙伴系统"最小可用块"的分配策略:从请求的 order 开始,逐级向上查找第一个…

作者头像 李华
网站建设 2026/10/19 20:42:51

作业一难就放弃?把「扛得住的心韧力」做成训练闭环

技术向 / 干货。面向想用「系统」替代「反复讲道理」的家长与开发者。 作者:学心教研 0. 结论先行 面对孩子在书桌前「一遇到难题就退缩发脾气」,很多家长习惯用「坚持就是胜利」「再动动脑子」这类道理去施压。但从认知神经机制来看,孩子一难…

作者头像 李华
网站建设 2026/10/16 2:10:35

影石系统组 一二面OC面经

一面1. 封装、继承、多态分别是什么?什么是封装?继承有哪些继承方式?封装:将属性和方法封装到类中,隐藏内部实现细节,对外提供访问接口,保护数据。继承:子类复用父类的成员&#xff…

作者头像 李华