Flink基础之Session-Cluster原理详解:共享集群的利与弊

摘要

讲透 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 集群,背后是六步:

在这里插入图片描述

  1. 本地执行 yarn-session.sh(加 -d 后台运行),CliFrontend 组装启动配置,向 YARN RM 提交应用,同时把 flink-dist JAR 和配置上传到 HDFS。
  2. RM 选择一个 NM 启动 AM 容器
  3. AM 内启动 Flink 框架本体:Dispatcher + JobMaster 框架(注意:没有用户代码,只有框架),打开 REST 端口等待作业提交。
  4. Flink 的 ResourceManager 向 YARN RM 申请初始 TaskManager 容器
  5. TaskManager 启动并注册到 JobManager,Slot 上报进共享资源池,集群进入待命状态。
  6. 本地输出 "Flink Session Cluster started successfully" 和 JobManager 地址

关键认知:Session 启动时没有用户 main()。用户代码是在后续每次 flink run 时由本地 Client 执行的——这正是「集群常驻、作业即插即用」的根基。

# 启动常驻 Session 集群(后台运行)
bin/yarn-session.sh -d -nm flink-session

三、作业如何提交到 Session 集群

集群就绪后,任意作业通过 flink run -t yarn-session 提交,链路四步:

在这里插入图片描述

  1. 本地 Client 执行用户 main(),生成 JobGraph(与 Application 模式一样在 Client 侧完成图构建)。
  2. 通过 REST 提交到常驻集群的 Dispatcher,同时上传作业 JAR。
  3. Dispatcher 为该作业创建 JobMaster 实例(每作业一个)。
  4. 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 集群的生命周期独立于作业,运维上要明确几个动作:

# 查看 Session 应用状态
yarn application -list | grep flink-session

# 停止 Session 集群(作业会一起失败!)
yarn application -kill <applicationId>

# 查看集群日志
yarn logs -applicationId <applicationId>

三个必须建立的认知:

  1. 杀掉 Session 集群 = 杀掉上面所有作业。停止集群前必须先确认没有重要作业在跑。
  2. Session 集群需要 HA。JobManager 是单点,不配 HA 的话 JobManager 一挂,集群上所有作业一起失败。
  3. Session 空闲时资源不释放(除非配了 idle 超时)。常驻 TM 占着 YARN 的资源,集群长期空转会造成浪费——这也是它「资源效率高」的另一面:高是相对复用而言,空转时的浪费同样真实。

七、配置与常用命令

# 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
# 启动 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

八、五个真实踩坑

  1. 作业提交后一直 SCHEDULED 不运行。Session 的 Slot 池被占满了——其他作业把资源吃光了。先 flink list 看集群上有多少作业,再决定是等、扩 TM 还是换 Application。
  2. 一个作业的背压/状态膨胀拖垮全集群。共享 TM 时,某个作业 RocksDB 状态暴涨会吃满托管内存,同 TM 的其他作业跟着变慢。Session 场景下这类「隔山打牛」问题最难排查——最终解法往往是给重作业单独开 Application。
  3. 杀集群前没确认作业yarn application -kill 一按,集群上所有作业一起陪葬,且没有恢复机制(除非配了 HA + 手动重启集群从 Checkpoint 恢复)。运维脚本里必须加确认步骤。
  4. Session 集群不配 HA。JobManager 单点 + 常驻 = 风险放大:本来 Application 模式下 JM 挂了只影响一个作业,Session 下影响所有。生产用 Session 必须配 high-availability
  5. 把 Session 当 Application 用。给每个「重要作业」都提交到共享 Session,隔离性、可靠性全无。判断标准:这个作业挂了能不能接受跟别人一起挂?不能就上 Application。

Session Cluster 的本质,是用「生命周期解耦 + 资源池共享」换提交速度和资源利用率:一次启动、长期待命,作业即插即用,代价是隔离缺失和单点放大。理解「集群与作业解耦」「共享 Slot 池先到先得」「杀集群 = 杀全部作业」这三点,Session 的架构、运维和选型就都通了——它适合快速迭代的共享场景,但不该成为生产作业的默认归宿。

posted @ 2026-09-14 13:18  starzy  阅读(5)  评论(0)    收藏  举报