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 只做决策。

在这里插入图片描述

它的核心职责有四块:

  1. 作业调度:接收 Client 提交的 JobGraph,展开为 ExecutionGraph,把任务调度到各个 TaskManager 的 Slot 上。
  2. 资源管理:维护整个集群的 Slot 池,负责分配、回收、动态申请。
  3. 容错协调:作为 Checkpoint 的协调者,触发快照、收集完成信号;处理 TaskManager 故障,按重启策略恢复作业。
  4. 对外接口:提供 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 内部经历四步:

在这里插入图片描述

  1. Dispatcher 接收 JobGraph,创建 JobMaster:JobGraph 是上一篇文章里 Client 优化好的可序列化提交单元。
  2. JobMaster 构建 ExecutionGraph:把每个 JobVertex(算子链)按并行度展开成多个 ExecutionVertex,每个 ExecutionVertex 对应一个 Task 执行单元,并挂上 Execution 状态机(CREATED → SCHEDULED → DEPLOYING → RUNNING → FINISHED/FAILED)。
  3. 申请并分配 Slot:JobMaster 向 ResourceManager 申请 Slot;Slot 不够时 ResourceManager 动态申请新 TaskManager 或等待释放。这里有个重要机制叫 Slot 共享(Slot Sharing):默认情况下,同一作业的不同任务可以共享一个 Slot(前提是算子链和任务数量匹配),大幅提升 Slot 利用率。
  4. 部署任务: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 + 外部协调器选主

  1. Leader 选举:多个 JobManager 进程同时启动,通过外部协调器竞争 Leader(Active)身份。ZooKeeper 用临时节点 + 会话超时判定失联;K8s 用 ConfigMap 的 lease 机制。
  2. 元数据持久化:Active JobManager 把 JobGraph 写入 high-availability.storageDir(HDFS/S3),用户代码存入 BlobStore,Checkpoint 照常写远端。
  3. 故障切换:协调器发现 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

七、四个真实踩坑

  1. 没配 HA,JobManager 是单点。这是 Flink 集群最常见的事故根源之一。JobManager 进程挂掉(堆内存 OOM、宿主机宕机、升级误操作),所有作业一起失败。生产环境第一件事就是把 high-availability 配起来。
  2. RPC 端口与 REST 端口混淆。JobManager 的 RPC 端口(默认 6123)用于与 TaskManager 通信,REST 端口(8081)用于对外接口。-m 连接、Web UI、curl 全走 REST;配错端口报 Connection refused 时先分清是哪个。
  3. JobManager 内存只调堆,忽略堆外jobmanager.heap.size 只配 JVM 堆;网络缓冲、元数据等堆外内存不足同样会崩。1.10 之后统一用 jobmanager.memory.process.size(总内存),别再用老参数按堆配置。
  4. 作业过多挤压一个 JobMaster 的性能。每作业一个 JobMaster,但都跑在同一个 JobManager 进程里。几百个作业共享一个进程时,Checkpoint 协调、REST 查询可能互相拖慢。大集群按作业类型拆分多个 Flink 集群,比堆高配单集群更稳。

JobManager 是 Flink 集群的「大脑」:Dispatcher 接待、JobMaster 调度、ResourceManager 管资源、BlobServer 管代码、Heartbeat 管存活,五者共处一个进程;它把所有「状态」都放在外部存储,因此能靠 Active/Standby 实现秒级接管。理解了「JobManager 只决策不执行、无状态所以可 HA」这两点,Flink 集群的运维排障就抓住了主干。

posted @ 2026-09-12 08:23  starzy  阅读(10)  评论(0)    收藏  举报