摘要
讲透 Flink Session Cluster 的完整原理:常驻共享集群的架构(Dispatcher + 共享 TaskManager 资源池)、yarn-session.sh 的启动流程、作业提交到 Session 集群的链路、共享 Slot 池的资源竞争机制,并给出 Session 与 Application 的全面对比、生命周期运维要点与五个真实踩坑点。
关键词
Flink、Session Cluster、yarn-session、Dispatcher、共享 Slot、JobManager、常驻集群、资源池、生命周期、Application
上一篇讲 Flink on YARN 时对比了三种模式,其中 Session 模式一句话带过:「集群常驻、多作业共享」。但 Session Cluster 远不是一句「共享」能概括的------它是 Flink 里生命周期与作业完全解耦的典型架构,启动一次、长期待命、任意作业随时提交。理解它的启动流程、提交链路和资源竞争机制,才能真正用对它。
这一篇把 Session Cluster 拆开:它长什么样、怎么起来的、作业怎么进去的、资源怎么竞争的、以及什么场景该用它。
一、Session Cluster 架构全景
Session Cluster 是一个常驻运行的 Flink 集群 (YARN 上表现为一个长期存活的应用),核心特征就一句话:集群和作业的生命周期是解耦的------先有集群,后提交任意多个作业,作业结束集群照常运行。

架构要点:
- AM 容器内运行 JobManager:Dispatcher(统一接收所有作业提交)+ 每个作业一个 JobMaster + ResourceManager(管理共享 Slot 池)+ BlobServer + Web UI。
- 多个 TaskManager 常驻,Slot 汇总成共享资源池,所有作业从这个池子里申请资源。
- Web UI 一个页面能看到集群上所有作业,这是 Session 运维上的一个隐藏便利。
与 Application 模式最大的不同在资源模型:Session 是「一个池子大家分」,Application 是「每人一亩三分地」。这个差异决定了它所有的优缺点。
二、Session 集群的启动流程
用 yarn-session.sh 启动一个 Session 集群,背后是六步:

- 本地执行
yarn-session.sh(加-d后台运行),CliFrontend 组装启动配置,向 YARN RM 提交应用,同时把 flink-dist JAR 和配置上传到 HDFS。 - RM 选择一个 NM 启动 AM 容器。
- AM 内启动 Flink 框架本体 :Dispatcher + JobMaster 框架(注意:没有用户代码,只有框架),打开 REST 端口等待作业提交。
- Flink 的 ResourceManager 向 YARN RM 申请初始 TaskManager 容器。
- TaskManager 启动并注册到 JobManager,Slot 上报进共享资源池,集群进入待命状态。
- 本地输出 "Flink Session Cluster started successfully" 和 JobManager 地址。
关键认知:Session 启动时没有用户 main() 。用户代码是在后续每次 flink run 时由本地 Client 执行的------这正是「集群常驻、作业即插即用」的根基。
bash
# 启动常驻 Session 集群(后台运行)
bin/yarn-session.sh -d -nm flink-session
三、作业如何提交到 Session 集群
集群就绪后,任意作业通过 flink run -t yarn-session 提交,链路四步:

- 本地 Client 执行用户 main(),生成 JobGraph(与 Application 模式一样在 Client 侧完成图构建)。
- 通过 REST 提交到常驻集群的 Dispatcher,同时上传作业 JAR。
- Dispatcher 为该作业创建 JobMaster 实例(每作业一个)。
- JobMaster 从共享 Slot 池申请 Slot,把任务部署到已有 TaskManager 上。
注意与 Application 模式的对照:这里没有「启动集群」这一步,因为集群早已存在。所以 Session 的提交速度远快于 Application------省掉的是整个「申请 AM → 启动 JobManager → 申请 TM」的集群拉起过程。
四、资源管理:共享 Slot 池的竞争机制
Session 的资源管理核心是共享 Slot 池:
- 所有作业从同一个池子里申请 Slot,先到先得。
- 池不够时,Flink 的 ResourceManager 按需向 YARN 申请新的 TaskManager 容器 (扩容);空闲时可通过
slot.idle.timeout等配置释放(缩容)。 - 作业之间共享同一批 TaskManager,跨作业存在资源竞争:作业 A 的一个重任务(比如 RocksDB 状态读写)可能拖慢与它共享 TM 的作业 B。
这是 Session 与 Application 的分水岭:Session 用隔离换速度。提交快、资源复用率高,代价是作业之间互相影响、JobManager 单点连累所有作业。
五、Session vs Application:什么场景选谁
| 维度 | Session | Application |
|---|---|---|
| 集群生命周期 | 常驻,与作业解耦 | 随作业启停 |
| main() 位置 | 本地 Client | 集群内 AM |
| 提交速度 | 快(集群已就绪) | 慢(先起集群) |
| 资源隔离 | 差(共享竞争) | 好(独立) |
| 故障影响 | JM 单点连累全部 | 仅影响本作业 |
| 资源效率 | 高(复用池) | 低(每作业一套) |
| 适用场景 | 多小作业、快速迭代 | 生产、大作业、隔离要求 |
我的判断 :Session 最典型的落地场景是开发测试环境和 Ad-hoc 查询------团队共享一个常驻集群,提交 SQL 或小作业秒级出结果。生产环境的常态化作业,除非作业量极大且确实能接受共享,否则 Application 更稳。
六、生命周期管理与运维
Session 集群的生命周期独立于作业,运维上要明确几个动作:
bash
# 查看 Session 应用状态
yarn application -list | grep flink-session
# 停止 Session 集群(作业会一起失败!)
yarn application -kill <applicationId>
# 查看集群日志
yarn logs -applicationId <applicationId>
三个必须建立的认知:
- 杀掉 Session 集群 = 杀掉上面所有作业。停止集群前必须先确认没有重要作业在跑。
- Session 集群需要 HA。JobManager 是单点,不配 HA 的话 JobManager 一挂,集群上所有作业一起失败。
- Session 空闲时资源不释放(除非配了 idle 超时)。常驻 TM 占着 YARN 的资源,集群长期空转会造成浪费------这也是它「资源效率高」的另一面:高是相对复用而言,空转时的浪费同样真实。
七、配置与常用命令
yaml
# flink-conf.yaml 关键配置
# Session 集群的 JobManager 内存(AM 容器内存)
jobmanager.memory.process.size: 2048m
# TaskManager 内存(= 每个 TM 容器内存)
taskmanager.memory.process.size: 4096m
# 每个 TM 的 Slot 数(决定资源池大小)
taskmanager.numberOfTaskSlots: 4
# 空闲 Slot 超时释放(默认 -1 不释放,配 5min 则空闲 5 分钟释放 TM)
slot.idle.timeout: 300000
# 作业提交到 Session 时并行度默认值
parallelism.default: 2
bash
# 启动 Session 集群(指定名称,后台)
bin/yarn-session.sh -d -nm flink-session
# 提交作业到已启动的 Session 集群
bin/flink run -t yarn-session -c com.example.MainClass ./app.jar
# 或先拿到 Session 的 JobManager 地址后直接指定
bin/flink run -m <jobmanager-host>:8081 -c com.example.MainClass ./app.jar
八、五个真实踩坑
- 作业提交后一直 SCHEDULED 不运行 。Session 的 Slot 池被占满了------其他作业把资源吃光了。先
flink list看集群上有多少作业,再决定是等、扩 TM 还是换 Application。 - 一个作业的背压/状态膨胀拖垮全集群。共享 TM 时,某个作业 RocksDB 状态暴涨会吃满托管内存,同 TM 的其他作业跟着变慢。Session 场景下这类「隔山打牛」问题最难排查------最终解法往往是给重作业单独开 Application。
- 杀集群前没确认作业 。
yarn application -kill一按,集群上所有作业一起陪葬,且没有恢复机制(除非配了 HA + 手动重启集群从 Checkpoint 恢复)。运维脚本里必须加确认步骤。 - Session 集群不配 HA 。JobManager 单点 + 常驻 = 风险放大:本来 Application 模式下 JM 挂了只影响一个作业,Session 下影响所有。生产用 Session 必须配
high-availability。 - 把 Session 当 Application 用。给每个「重要作业」都提交到共享 Session,隔离性、可靠性全无。判断标准:这个作业挂了能不能接受跟别人一起挂?不能就上 Application。
Session Cluster 的本质,是用「生命周期解耦 + 资源池共享」换提交速度和资源利用率:一次启动、长期待命,作业即插即用,代价是隔离缺失和单点放大。理解「集群与作业解耦」「共享 Slot 池先到先得」「杀集群 = 杀全部作业」这三点,Session 的架构、运维和选型就都通了------它适合快速迭代的共享场景,但不该成为生产作业的默认归宿。