Flink 集群运行模式
文章目录
一、三种运行模式的划分依据
Flink 集群运行模式根据两个条件划分为三种类型:
| 划分维度 | 问题 |
|---|---|
| 条件 1 | 集群生命周期与资源隔离方式 — 共享还是独占? |
| 条件 2 | main 方法在哪里执行 — Client 端还是 JobManager 端? |
三种模式:
Session Mode ──── 共享集群,main 在 Client
Per-Job Mode ──── 独占集群,main 在 Client
Application Mode ─── 独占集群,main 在 JobManager
二、Session Mode(会话模式)
2.1 核心架构
Session 集群(提前启动,长期运行)
┌───────────────────────────────────────────────┐
│ JobManager(共享) │
│ │ │
│ ┌─────────┼─────────┐ │
│ ▼ ▼ ▼ │
│ Job-1 Job-2 Job-3 ← 多个作业共享 │
│ │ │ │ │
│ └─────────┼─────────┘ │
│ ▼ │
│ TaskManager(s)(共享) │
└───────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
Client-1 Client-2 Client-3
关键特征:JobManager 和 TaskManager 预先启动,多个作业共享同一套集群资源,JobManager 生命周期独立于作业——作业停止不影响集群存活。
2.2 优缺点
| 维度 | 评价 |
|---|---|
| ✅ 资源利用率高 | 多作业共享集群,资源充分复用 |
| ✅ 运维简单 | 一个集群管理所有作业 |
| ✅ 启动快 | 集群预启动,作业提交即运行,无需等待资源分配 |
| ❌ 资源隔离弱 | 作业间资源竞争,Job-1 占满可能导致 Job-2 无法提交 |
| ❌ 伸缩性弱 | TaskManager 启动时固定,难以动态扩缩(除非配合 Native K8s) |
三、Per-Job Mode(每作业模式)
3.1 核心架构
Job-1 Job-2
┌──────────────────────┐ ┌──────────────────────┐
│ JobManager-1(独占) │ │ JobManager-2(独占) │
│ │ │ │ │ │
│ TaskMgr-A TaskMgr-B │ │ TaskMgr-C TaskMgr-D │
│ [Slot][Slot][Slot] │ │ [Slot][Slot] │
└──────────────────────┘ └──────────────────────┘
独立的集群实例 独立的集群实例
关键特征:每个作业拥有一套独立的 JobManager + TaskManager,Job-1 和 Job-2 之间的集群资源完全隔离。作业执行完毕后,整个集群销毁释放。
3.2 优缺点
| 维度 | 评价 |
|---|---|
| ✅ 资源隔离强 | 作业间互不影响 |
| ✅ Slot 灵活 | 每个作业可按需配置 Task Slot 数量 |
| ❌ 资源浪费 | 每作业都启动一个 JobManager,消耗额外计算资源 |
| ❌ 管理复杂 | 大量 JobManager 实例,依赖 ClusterManager(YARN/K8s)统一管理 |
| ❌ 启动慢 | 每次提交都需要启动整套集群 |
四、Session vs Per-Job 的共同痛点
无论 Session 还是 Per-Job,main 方法都在 Client 端执行,带来一系列问题:
Client 端执行 main 方法的问题:
1. 依赖 JAR 下载 → 每次提交都要从远端下载,大 JAR(十几到几百 MB)消耗带宽
2. JobGraph 生成 → 消耗 Client 本地 CPU 资源
3. JAR 上传 → 每次提交都要通过 RPC 上传 JAR 到 JobManager,重度网络消耗
4. 阻塞式提交 → 提交是同步阻塞的,多用户提交需要排队等待
5. Client 瓶颈 → 单 Client 提交多作业时压力巨大,稳定性无法保证
传统模式:Client 承载了太多
┌──────────┐ 下载依赖 ┌──────────┐ 上传 JAR ┌──────────┐
│ 远端仓库 │ ──────────────────→ │ Client │ ──────────────────→ │JobManager│
└──────────┘ (网络消耗) └──────────┘ (网络消耗) └──────────┘
│
执行 main 方法
生成 JobGraph
(CPU 消耗)
五、Application Mode(应用模式)
5.1 核心理念
把 main 方法从 Client 端搬到 JobManager 端执行!
Application Mode 的变革:
之前:Client 做所有重活 → JobManager 只是调度
现在:Client 只发命令 → JobManager 承担 main 方法执行 + JobGraph 生成
5.2 架构对比
传统模式(Session / Per-Job):
Client JobManager
│ │
├─ 下载依赖 JAR ├─ 接收 JobGraph
├─ 执行 main 方法 ├─ 生成 ExecutionGraph
├─ 生成 JobGraph └─ 调度 Task
└─ 上传 JAR + JobGraph ──────────→
Application Mode:
Client JobManager(管理节点)
│ │
└─ 只发命令 ──────→ ├─ 从 DFS 拉取依赖 JAR
├─ 执行 main 方法
├─ 生成 JobGraph
├─ 生成 ExecutionGraph
└─ 调度 Task
5.3 Application Mode 的工作流程
1. Client 发送提交命令
│
2. JobManager 从分布式文件系统(DFS/HDFS)拉取依赖 JAR
│
3. JobManager 执行 main 方法 → 生成 JobGraph
│
4. JobManager 调度 → TaskManager 执行
│
5. 一个 Application = 一套独立集群(类似 Per-Job)
一个 Application 内可以包含多个 Job
5.4 优缺点
| 维度 | 评价 |
|---|---|
| ✅ Client 轻量化 | Client 只需发命令,无需本地下载/上传/执行,负载大幅降低 |
| ✅ 网络优化 | JAR 从 DFS 直接拉取到集群,避免 Client ↔ JobManager 的大流量传输 |
| ✅ 避免排队 | 每个 Application 独立执行 main 方法,不再阻塞提交 |
| ✅ Application 级隔离 | 每个 Application 启动独立集群,资源隔离 |
| ❌ 只支持 YARN / K8s | 暂不支持 Standalone |
| ❌ K8s 需预构建镜像 | K8s 上需要提前把用户程序打成 Docker 镜像 |
六、三种模式全景对比
| 维度 | Session | Per-Job | Application |
|---|---|---|---|
| 集群生命周期 | 独立于作业,长期运行 | 绑定作业,作业结束即销毁 | 绑定 Application,结束即销毁 |
| 资源隔离 | 弱(共享集群) | 强(独占集群) | 强(独占集群) |
| main 方法位置 | Client | Client | JobManager |
| JobGraph 生成位置 | Client | Client | JobManager |
| Client 负载 | 高 | 高 | ✅ 低 |
| 资源利用率 | ✅ 高 | ❌ 低 | 中 |
| 提交速度 | ✅ 快(集群预热) | ❌ 慢(每次启动集群) | 中 |
| 运维复杂度 | ✅ 低 | ❌ 高 | 中 |
| 适用场景 | 短作业、多作业共享 | 大作业、需严格隔离 | 流平台、多用户提交 |
| 支持平台 | Standalone/YARN/K8s | YARN/K8s | 仅 YARN / K8s |
七、如何选择运行模式?
开始
│
┌─ 需要强资源隔离? ──┐
│ 否 │ 是
▼ ▼
Session Mode ┌─ main 在哪执行? ──┐
(短作业/开发测试) │ Client │ JobManager
▼ ▼
Per-Job Mode Application Mode
(大作业/生产) (流平台/多租户)
八、小结
- Flink 有三种集群运行模式,按集群生命周期和main 方法位置两个维度划分
- Session 适合短作业共享集群,资源利用率高但隔离弱
- Per-Job 适合大作业独占集群,隔离强但资源浪费
- Application Mode 将 main 方法迁到 JobManager,解决了传统模式 Client 瓶颈问题,是流平台多租户场景的未来方向
- Application Mode 目前仅支持 YARN 和 K8s