Flink 弹性伸缩(Elastic Scaling)Adaptive Scheduler、Reactive Mode 与外部资源声明

1. 弹性伸缩到底解决什么问题?

核心问题不是"能不能调并发",而是"资源经常不稳定":

  • 提交时集群 slot 不够:以前要么卡住、要么失败、要么你手动降并发重提
  • 运行中 TaskManager 掉线:默认调度器可能触发失败/重启策略;而自适应调度器可以先自动缩容保证作业继续跑
  • 负载变化:输入速率变高/变低,理想情况是作业能自动吃满资源或释放资源,而不用你做编排

2. Adaptive Scheduler(Streaming)怎么工作?

Adaptive Scheduler 的核心能力:根据可用 slots 动态调整作业并发度

2.1 基本行为

  • 如果 slot 不够跑满你配置的并发:它会自动 降低并发,让作业先跑起来
  • 运行中新增 slot:它会自动 提升并发(直到达到你配置的并发上限)
  • 对 TaskManager 丢失更"抗打":掉了就缩容继续跑,不是硬等资源或频繁失败

2.2 背后的关键:声明式资源管理(Declarative Resource Management)

传统模式是"我要 N 个 slot"。自适应调度器更像"我希望拿到这些资源上限/边界",由 ResourceManager 尽力满足。

更进一步:当 JobMaster 在运行时拿到更多资源,会自动用最近可用的状态点(最新 savepoint/最新 checkpoint 语义上取决于模式)触发 rescale,减少外部编排依赖。

3. Reactive Mode:让作业永远"吃满整个集群"

Reactive Mode 是 Adaptive Scheduler 的一个特殊模式,假设 单集群单作业(通常用 Application Mode 强制)。

3.1 Reactive Mode 的特点

  • 忽略你提交时配置的 parallelism,把它当成"无穷大"
  • 作业永远使用集群当前所有可用资源
  • 加 TaskManager ⇒ 自动扩容
    减 TaskManager ⇒ 自动缩容

3.2 为什么它特别适合做自动扩缩

Reactive Mode 的 rescale 事件会 重启作业 ,并从最新完成的 checkpoint恢复:

  • 不需要额外触发 savepoint(省掉人工 rescale 的典型步骤)
  • rescale 后会重放多少数据,取决于 checkpoint 间隔
  • 恢复耗时和状态大小强相关

因此,最常见的"自动扩缩"组合是:

  • 外部系统只管增减 TaskManager(K8S 副本数、云上 ASG 等)
  • Flink 自己负责把并发调到"当前资源下能跑到的最大值",并保证状态恢复

从 Flink 1.18.x 开始,如果你希望 Adaptive Scheduler 能响应"输入速率变化/工作负载变化"而做更智能的 rescale,仅靠 slot 变化可能不够,需要用 外部化声明式资源管理在运行时重新声明资源边界。

这是一个 MVP 特性,社区希望用户反馈。它提供了一个 REST API,可以对运行中的 job 做"按 vertex 维度"的并发上下界声明,效果上很像"在线 rescale 控制面"。

4.1 REST API 示例

接口:

  • PUT /jobs/<job-id>/resource-requirements

请求体(按 vertex id 设置并发上下界):

json 复制代码
{
  "<first-vertex-id>": {
    "parallelism": { "lowerBound": 3, "upperBound": 5 }
  },
  "<second-vertex-id>": {
    "parallelism": { "lowerBound": 2, "upperBound": 3 }
  }
}

你可以用 curl 这样调用(示例):

bash 复制代码
curl -X PUT "http://<jm-host>:8081/jobs/<job-id>/resource-requirements" \
  -H "Content-Type: application/json" \
  -d '{
    "<vertex-1>": {"parallelism": {"lowerBound": 4, "upperBound": 16}},
    "<vertex-2>": {"parallelism": {"lowerBound": 2, "upperBound": 8}}
  }'

实际体验上,它也被 UI 暗示成"缩放按钮":你在 Flink Web UI 的 Job Overview 里可以尝试 up-scale/down-scale。

4.2 两个典型使用场景

  • Session Cluster:多作业抢资源,需要更细粒度地控制每个作业拿到多少
  • Application Cluster + Active Resource Manager(例如某些场景下依赖 Flink 去"贪婪拉起 TaskManager"):你仍然希望拥有类似 Reactive Mode 的 rescale 能力

如果你希望一站式自动伸缩体验,文档也提到可结合 Apache Flink Kubernetes Operator 来做。

5. 如何启用 Adaptive Scheduler

在集群级别切换调度器(替代默认 scheduler):

yaml 复制代码
jobmanager.scheduler: adaptive

Adaptive Scheduler 的相关参数都以 jobmanager.adaptive-scheduler.* 为前缀。

重要提醒:

  • Adaptive Scheduler 仅适用于 Streaming 作业
  • 提交 Batch 作业时,Flink 会走 Batch 的默认调度器(通常是 Adaptive Batch Scheduler)

6. Reactive Mode 快速上手(本机单机演示)

下面是文档里的演示流程(Application Mode):

1)把示例作业放进 lib:

bash 复制代码
cp ./examples/streaming/TopSpeedWindowing.jar lib/

2)以 Reactive Mode 启动 standalone application,并设置 checkpoint:

bash 复制代码
./bin/standalone-job.sh start \
  -Dscheduler-mode=reactive \
  -Dexecution.checkpointing.interval="10s" \
  -j org.apache.flink.streaming.examples.windowing.TopSpeedWindowing

3)启动第一个 TaskManager:

bash 复制代码
./bin/taskmanager.sh start

扩容:再启动一个 TaskManager

bash 复制代码
./bin/taskmanager.sh start

缩容:停止一个 TaskManager

bash 复制代码
./bin/taskmanager.sh stop

你会看到作业随着 TaskManager 数量变化发生 rescale(触发重启并从最新 checkpoint 恢复)。

7. 关键配置与生产建议

7.1 必须配置 checkpoint(尤其有状态作业)

Reactive Mode 的 rescale 是从最新完成 checkpoint 恢复:

  • 不开 checkpoint:状态丢失风险很高
  • checkpoint 也决定重启策略:如果没配置重启策略,Reactive Mode 可能直接 fail 而不是"缩放继续跑"

7.2 资源等待与稳定窗口:避免频繁重启

Reactive Mode 下默认行为很"激进":

  • jobmanager.adaptive-scheduler.resource-wait-timeout 默认 -1:永远等资源
  • jobmanager.adaptive-scheduler.resource-stabilization-timeout 默认 0:资源一到就立刻调度

问题:TaskManager 如果是一个个慢慢连进来,就会导致"每来一个 TM 就重启一次"。

对策:

  • 增大 resource-stabilization-timeout:等资源稳定后再跑
  • 配置 jobmanager.adaptive-scheduler.min-parallelism-increase:只有并发提升达到一定幅度才触发扩容重启
  • jobmanager.adaptive-scheduler.scaling-interval.min 控制两次缩放的最小间隔(默认 30s)
  • 必要时用 jobmanager.adaptive-scheduler.scaling-interval.max 强制在一定时间后触发一次缩放(默认关闭)

7.3 下缩可能"卡 50 秒":心跳超时导致的等待

如果缩容时 TaskManager 被不优雅杀掉(SIGKILL 而不是 SIGTERM),Flink 需要等心跳超时才确认它离线,常见会卡一段时间(文档提到大约 50 秒)。

可以调低 heartbeat.timeout,但要谨慎:

  • 心跳 timeout 太低,在网络抖动或长 GC 时可能误判 TM 失联,导致不必要的重启
  • 同时确保 heartbeat.interval < heartbeat.timeout

7.4 并发影响方式:只能用 maxParallelism 施加上限

Reactive Mode 下你显式 set 的 parallelism 会被忽略。你能影响的主要是:

  • 作业/算子 maxParallelism(上限 2^15 = 32768)

但 maxParallelism 设得太高会增加内部结构维护成本,性能可能变差。建议按业务可接受的扩展上限设置,不要无脑拉满。

8. 限制与取舍

8.1 Adaptive Scheduler 的限制

  • 仅支持 Streaming 作业
  • 不支持 partial failover:默认 scheduler 可以按 region 局部重启;Adaptive Scheduler 会整作业重启
    对"纯并行、无强依赖"的作业会影响恢复时间
  • 每次 scaling 都会触发 job/task 重启,task attempt 数会增加

8.2 Reactive Mode 的限制(更严格)

  • 部署形态限制较多:主要支持 Standalone Application(含 Docker Application、Standalone K8S Application Cluster)
  • 不支持 Standalone Session Cluster
  • 不支持单集群多作业(Reactive 假设单作业吃满资源)
  • 文档明确提示:这仍是实验性能力,默认 scheduler 的一些能力尚未覆盖

9. 你该怎么选?

一个实用决策口径:

  • 你是 Streaming,集群资源会波动,且希望 TM 掉线时作业自动缩容继续跑

    选 Adaptive Scheduler(jobmanager.scheduler: adaptive

  • 你是 Streaming,想做"真正的自动扩缩",让作业永远吃满集群资源

    选 Reactive Mode(Application Mode)+ 必开 checkpoint

    外部系统只负责增减 TaskManager

  • 你是 Batch,希望并发、Join、数据分布在运行时更贴合真实数据

    选 Adaptive Batch Scheduler(Batch 默认)

相关推荐
REDcker5 小时前
HTTP 状态码清单大全
网络·网络协议·http
Go_Zezhou5 小时前
render快速部署网站和常见问题解决
运维·服务器·开发语言·python·github·状态模式
小白电脑技术5 小时前
如何修改电脑名称及其实际作用
运维·网络·电脑
酣大智5 小时前
TCP与UDP协议
运维·网络·网络协议·tcp/ip
小苏兮5 小时前
【把Linux“聊”明白】命令行参数与环境变量
linux·运维·服务器·学习
大闲在人5 小时前
使用有向莱顿算法进行供应链/物料流转网络的集群划分
网络·算法
cuijiecheng20186 小时前
Linux下inih库的使用
linux·运维·服务器
一起养小猫8 小时前
Flutter for OpenHarmony 实战:打造天气预报应用
开发语言·网络·jvm·数据库·flutter·harmonyos
qianshang23313 小时前
SQL注入学习总结
网络·数据库·渗透