Flink基础之JobManager详解:集群的大脑如何调度作业
摘要
讲清 JobManager 的完整职责与内部结构:Dispatcher 接收作业、JobMaster 调度 ExecutionGraph、ResourceManager 管理 Slot、Checkpoint 协调与故障恢复,以及 ZooKeeper/K8s 高可用架构;并给出关键配置与四个真实踩坑点。
关键词
Flink、JobManager、JobMaster、Dispatcher、ResourceManager、Slot、Checkpoint、高可用、HA、ExecutionGraph
上一篇文章讲了 Client 提交 JobGraph 的完整链路。提交之后,接力棒交到了谁手里?是 JobManager——Flink 集群里唯一不执行业务计算、却掌控一切的「大脑」。它接收作业、调度任务、分配资源、协调 Checkpoint、处理故障,任何一个环节出问题,整个集群的作业都会受影响。
这一篇把 JobManager 拆开:它内部到底有哪几个角色、一个作业从提交到运行要经过它的哪些环节、它挂了怎么办。
一、JobManager 的职责全景
先给 JobManager 一个定位:它是 Flink 集群的调度与协调中枢,负责「想清楚」,不负责「干活」。所有实际计算都在 TaskManager 上执行,JobManager 只做决策。

它的核心职责有四块:
- 作业调度:接收 Client 提交的 JobGraph,展开为 ExecutionGraph,把任务调度到各个 TaskManager 的 Slot 上。
- 资源管理:维护整个集群的 Slot 池,负责分配、回收、动态申请。
- 容错协调:作为 Checkpoint 的协调者,触发快照、收集完成信号;处理 TaskManager 故障,按重启策略恢复作业。
- 对外接口:提供 Web UI(8081)和 REST API,用于提交、查询、取消作业。
一个容易忽略的事实:JobManager 是一个进程,进程里同时跑着多个角色。理解内部结构,是理解它所有行为的前提。
二、JobManager 进程内部的五个角色
2.1 Dispatcher:全局唯一的入口
所有作业提交的 REST 请求(无论来自 CLI、SQL Client 还是 Web UI)都先打到 Dispatcher。它的活儿很简单:为每个作业创建一个 JobMaster,然后就不再管这个作业了。Dispatcher 本身不参与调度。
2.2 JobMaster:每作业一个的调度大脑
这是 JobManager 里最重要的角色。一个作业对应一个 JobMaster,职责包括:
- 把 JobGraph 展开成 ExecutionGraph(按并行度拆出 ExecutionVertex);
- 调度 ExecutionVertex 到 Slot;
- 监控作业运行状态,处理任务失败与重启;
- 内含 CheckpointCoordinator,负责该作业的 Checkpoint 协调。
Dispatcher 与 JobMaster 的关系,可以类比「前台接待」和「项目负责人」:前台登记后交给对应的负责人,之后的事都是负责人的。
2.3 ResourceManager:全局唯一的资源中枢
管理集群的 Slot 池(SlotManager)。JobMaster 需要资源时向它申请 Slot;Slot 不够时,它负责向 YARN/K8s 申请新的 TaskManager(动态扩容),或等待 Standalone 集群中已有 Slot 释放。它还负责与外部资源系统的对接,是 Flink 能跑在各种资源调度框架上的关键。
2.4 BlobServer:二进制大对象存储
存放作业相关的 JAR 和用户代码(Blob)。TaskManager 部署任务时,需要从 BlobServer 拉取对应的用户代码。配了 HA 后,Blob 还会持久化到外部的 BlobStore,供新的 JobManager 接管时恢复。
2.5 HeartbeatManager:心跳监控
监控 JobManager ↔ TaskManager 之间的存活状态。心跳超时判定节点失联,触发相应的故障处理(重新分配该节点上的任务)。
再加上 Web UI / REST Server,这五个角色共同构成了 JobManager 进程。
三、作业调度流程:从 JobGraph 到运行
一个作业从提交到跑起来,在 JobManager 内部经历四步:

- Dispatcher 接收 JobGraph,创建 JobMaster:JobGraph 是上一篇文章里 Client 优化好的可序列化提交单元。
- JobMaster 构建 ExecutionGraph:把每个 JobVertex(算子链)按并行度展开成多个 ExecutionVertex,每个 ExecutionVertex 对应一个 Task 执行单元,并挂上 Execution 状态机(CREATED → SCHEDULED → DEPLOYING → RUNNING → FINISHED/FAILED)。
- 申请并分配 Slot:JobMaster 向 ResourceManager 申请 Slot;Slot 不够时 ResourceManager 动态申请新 TaskManager 或等待释放。这里有个重要机制叫 Slot 共享(Slot Sharing):默认情况下,同一作业的不同任务可以共享一个 Slot(前提是算子链和任务数量匹配),大幅提升 Slot 利用率。
- 部署任务:JobMaster 把 Task(含用户代码)部署到对应 TaskManager 的 Slot 上,Task 建立与上下游的数据连接后开始运行,并向 JobMaster 上报心跳与状态。
一句话概括:先建图、再占资源、最后部署。
四、Checkpoint 协调与故障恢复
4.1 JobMaster 内的 CheckpointCoordinator
前面几篇反复提到 Checkpoint,这里补上它的「发起方」:CheckpointCoordinator 内嵌在 JobMaster 里,负责:
- 按
execution.checkpointing.interval周期触发 Checkpoint; - 向 Source 注入 Barrier,随数据流传播;
- 收集各算子快照完成信号,全部完成后提交 Checkpoint 元数据。
所以 JobMaster 一旦出问题,正在进行的 Checkpoint 协调也会中断——这也是它需要 HA 的原因之一。
4.2 两类故障,两种恢复
- TaskManager 故障:该节点上的任务全部失败。JobMaster 检测到后,按作业配置的重启策略(
restart-strategy:fixed-delay / failure-rate / none)重新调度这些任务,从最近一次成功的 Checkpoint 恢复状态。这是日常最常见的故障,JobManager 本身无恙。 - JobManager 故障:这是「大脑宕机」。没有 HA 时,集群上所有作业一起失败,无法自动恢复。这就是下一节要讲的高可用。
五、JobManager 高可用(HA)
JobManager 是无状态的——它的「状态」全部存放在外部:JobGraph 在持久化存储里、用户代码在 BlobStore 里、作业运行状态在 Checkpoint 里。正因为无状态,才能做到主备切换。

HA 的核心是 Active/Standby + 外部协调器选主:
- Leader 选举:多个 JobManager 进程同时启动,通过外部协调器竞争 Leader(Active)身份。ZooKeeper 用临时节点 + 会话超时判定失联;K8s 用 ConfigMap 的 lease 机制。
- 元数据持久化:Active JobManager 把 JobGraph 写入
high-availability.storageDir(HDFS/S3),用户代码存入 BlobStore,Checkpoint 照常写远端。 - 故障切换:协调器发现 Active 失联后,Standby 竞争成为新 Leader,从持久化存储恢复 JobGraph 与用户代码,与存活的 TaskManager 重建连接,重新调度所有作业并从最近 Checkpoint 恢复。
关键配置(flink-conf.yaml):
# 启用 ZooKeeper HA(kubernetes 模式则用 high-availability: kubernetes)
high-availability: zookeeper
high-availability.zookeeper.quorum: zk1:2181,zk2:2181,zk3:2181
high-availability.storageDir: hdfs:///flink/ha
# 重启策略:固定延迟重启,最多 3 次,间隔 10 秒
restart-strategy: fixed-delay
restart-strategy.fixed-delay.attempts: 3
restart-strategy.fixed-delay.delay: 10s
判断:生产环境必须配 HA。不配的话,JobManager 进程一挂(OOM、机器宕机、误操作),集群全部作业一起陪葬,且无法自动恢复。
六、关键配置速查
# JobManager 进程总内存(JVM 堆 + 堆外,1.10+ 推荐用 process.size)
jobmanager.memory.process.size: 2048m
# RPC 端口(JobManager ↔ TaskManager 通信,勿与 REST 混淆)
jobmanager.rpc.address: 10.0.0.1
jobmanager.rpc.port: 6123
# REST / Web UI 端口
rest.port: 8081
# 每作业 Checkpoint 间隔
execution.checkpointing.interval: 60s
排查问题时,最常用的入口是 REST API:
# 查看集群上所有作业
curl http://jobmanager:8081/jobs/overview
# 查看某个作业的详细执行计划
curl http://jobmanager:8081/jobs/<jobId>/execution-result
# 查看 JobManager 日志(Standalone 部署)
tail -f $FLINK_HOME/log/flink-*-standalonesession-*.log
七、四个真实踩坑
- 没配 HA,JobManager 是单点。这是 Flink 集群最常见的事故根源之一。JobManager 进程挂掉(堆内存 OOM、宿主机宕机、升级误操作),所有作业一起失败。生产环境第一件事就是把
high-availability配起来。 - RPC 端口与 REST 端口混淆。JobManager 的 RPC 端口(默认 6123)用于与 TaskManager 通信,REST 端口(8081)用于对外接口。
-m连接、Web UI、curl 全走 REST;配错端口报Connection refused时先分清是哪个。 - JobManager 内存只调堆,忽略堆外。
jobmanager.heap.size只配 JVM 堆;网络缓冲、元数据等堆外内存不足同样会崩。1.10 之后统一用jobmanager.memory.process.size(总内存),别再用老参数按堆配置。 - 作业过多挤压一个 JobMaster 的性能。每作业一个 JobMaster,但都跑在同一个 JobManager 进程里。几百个作业共享一个进程时,Checkpoint 协调、REST 查询可能互相拖慢。大集群按作业类型拆分多个 Flink 集群,比堆高配单集群更稳。
JobManager 是 Flink 集群的「大脑」:Dispatcher 接待、JobMaster 调度、ResourceManager 管资源、BlobServer 管代码、Heartbeat 管存活,五者共处一个进程;它把所有「状态」都放在外部存储,因此能靠 Active/Standby 实现秒级接管。理解了「JobManager 只决策不执行、无状态所以可 HA」这两点,Flink 集群的运维排障就抓住了主干。

浙公网安备 33010602011771号