年前在客户现场排查一个挺有意思的问题:一套Flink集群配置了ZooKeeper高可用(High Availability),两个JobManager也都起来了,但作业一提交就失败,报错信息指向JobManager没有正确恢复集群元数据。查到最后发现,HA存储目录权限不对,JobGraph压根没有持久化成功,Standby节点接管后等于是个空壳集群。这类问题在Flink JobManager高可用(High Availability)的日常运维里太常见了,很多人以为配了ZooKeeper就是高可用,其实组件、持久化、数据生命周期、还有1.17之后引入的JobResultStore,每一环都可能出问题。
这篇文章我准备结合生产环境里的实战经验,把JobManager高可用从头到尾拆一遍:为什么必须做HA、选举和持久化怎么配合、数据在哪个阶段写到哪里、故障切换时具体发生了什么,以及JobResultStore怎么用。内容偏向原理加实操,适合正在维护Flink生产集群、设计容灾方案、或者准备系统梳理HA机制的朋友。
1. 为什么JobManager是"单点"里最不能挂的一个
1.1 JobManager的双重身份:控制大脑加调度中心
很多初学者会把Flink集群理解成"JobManager管作业,TaskManager管计算,两者各司其职"。这个说法没错,但它低估了JobManager的工作量。JobManager内部有Dispatcher、ResourceManager、JobMaster三个核心组件,三个组件合在一起,几乎承担了集群控制面的全部职责。
Dispatcher接收客户端提交的作业,负责调度JobMaster的创建,也是用户与集群交互的入口。ResourceManager负责集群资源的统一管理,包括Slot的申请、分配和释放。TaskManager启动后要主动向他注册,申请Slot也要走这里。JobMaster是每个作业的大脑,维护作业的ExecutionGraph,负责把Task部署到TaskManager,同时协调Checkpoint、故障恢复、作业状态转换等。
也就是说,作业能不能提交、能不能调度、能不能做Checkpoint、故障后能不能恢复,全部依赖JobManager。TaskManager再强,也只是一群等待指令的工人,工人之间不会自己排产和协作。
1.2 没有HA时,一次宕机到底会损失什么
先看一张表,理解一下JobManager挂掉后集群各部分的真实状态:
| 组件 | JM挂掉后的表现 | 实际影响 |
|---|---|---|
| TaskManager | 进程仍然活着,Slot继续被占用 | 无法接收新任务,心跳报错,逐渐与集群失联 |
| 运行中的作业 | ExecutionGraph无人维护 | Checkpoint停止,状态无法推进,作业最终失败 |
| 客户端 | 连接断开 | 无法查询状态、无法取消作业、无法提交新作业 |
| Checkpoint元数据 | 由JM管理 | 没有新的Completed Checkpoint产生,旧状态停留在本地或远端存储 |
没有HA的情况下,JobManager进程一挂,整个集群几乎立刻进入"脑死亡"状态。TaskManager短时间内不知道JobManager已经没了,仍然占着Slot,等心跳超时后才开始清理。这期间所有作业都没有人管理,Checkpoint也不做了,数据源还在继续生产数据,状态延迟越来越大,等运维手动拉起JobManager,作业基本已经处于失败或者不可恢复的状态。
更麻烦的是,默认情况下JobManager会把一些关键元数据写在本地磁盘。如果节点本身出问题(比如磁盘损坏、机器被回收),这个本地副本也会一起丢。手动重启之后,JobManager发现没有可恢复的JobGraph,只能创建一个空集群,所有作业都要从零提交,所有状态都要依赖最后那一次Checkpoint手工找回。
所以做Flink生产集群,HA不是可选项,是必选项。它不是为了让"JobManager不挂",而是为了让"挂了以后能快速、自动地恢复集群控制能力"。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JobManager高可用的三大支柱:选举、持久化、重连
2.1 Leader选举:谁拿到临时节点,谁就是老大
Flink的JobManager高可用,第一个核心机制是Leader选举。当前支持两种实现:ZooKeeper和Kubernetes。
以ZooKeeper为例,所有候选JobManager进程启动后会去ZooKeeper的指定路径下竞争一个临时节点。这个路径默认是/flink/leader/rest_server_lock和/flink/leader/jobmanager。竞争规则很简单:谁成功创建了那个临时节点,谁就是当前的Leader,其他节点成为Standby。
这里有几个关键点要理解:
- 临时节点由ZooKeeper的Session生命周期管理。如果Leader的ZooKeeper客户端会话超时或者断连,临时节点会自动消失。此时Standby节点通过Watcher机制立刻感知到Leader节点消失,马上发起新一轮
