2. 需求分析与架构设计:业务需求梳理、技术选型、系统架构分层设计

说实话,很多人在搭建调度系统时,上来就撸代码。我见过不少团队,写了三个月发现架构撑不住,推倒重来。嗯,这一章我们就聊聊,在写第一行代码之前,应该想清楚什么。

2.1 业务需求梳理:你到底要调度什么?

先别急着选技术栈。你得搞清楚,你的调度系统要解决什么问题。我个人习惯,先列一个需求清单。

核心需求清单(OLAP 场景)

  • 任务类型:SQL 查询、ETL 脚本、Spark/Flink 作业、数据导出
  • 触发方式:定时调度(cron)、依赖触发(上游完成)、手动触发、事件触发
  • 依赖管理:任务之间可以配置上下游依赖,形成 DAG
  • 重试与告警:失败自动重试(可配置次数和间隔)、钉钉/邮件告警
  • 资源隔离:不同业务线使用不同的资源队列,互不干扰
  • 日志与审计:每个任务的执行日志可追溯,支持实时查看

我在项目中遇到过一个问题:业务方说“我要每天凌晨 2 点跑数据”,结果实际上有 200 个任务都配了凌晨 2 点。调度器直接被打挂了。所以,需求里一定要加上“调度压力评估”。

避坑指南:我曾经接手过一个系统,任务依赖关系用 JSON 硬编码在配置文件里。后来业务扩张,依赖图变得跟蜘蛛网一样,根本没法维护。所以,依赖关系一定要支持可视化编辑和动态更新。

2.2 技术选型:Python、Java、Go 怎么选?

这是每次架构评审都会吵起来的话题。我直接说结论:没有银弹,看场景。

维度 Python Java Go
开发效率 极高,生态丰富(Airflow、Celery) 中等,Spring 生态成熟 中等,标准库强大
并发性能 较弱(GIL 限制) 强(JVM 调优) 极强(goroutine)
运维成本 低(解释型,部署简单) 高(JVM 参数、GC 调优) 低(编译成二进制,无依赖)
社区与生态 数据科学领域王者 企业级应用首选 云原生、微服务新贵
典型代表 Airflow、Dagster Oozie、Azkaban DolphinScheduler(调度核心)

我个人建议:

  • 如果团队以数据工程师为主,选 Python。快速出活,Airflow 直接拿来改改就能用。
  • 如果团队有 Java 背景,且系统需要深度集成 Hadoop/Spark 生态,选 Java。毕竟 Spark 就是 Scala/Java 写的。
  • 如果追求极致性能和低资源占用,选 Go。我最近一个项目就是用 Go 重写了调度核心,内存占用直接降了 60%。

注意:不要为了“炫技”而选 Go。如果你的团队没人写过 Go,光踩坑就能浪费一个月。技术选型要匹配团队能力。

2.3 系统架构分层设计:四层架构

好了,需求清楚了,语言选好了。接下来是重头戏——架构设计。我习惯把调度系统拆成四层:接入层、调度层、执行层、监控层。

为什么会这样分?说白了,每一层各司其职,互不干扰。你想想看,如果调度逻辑和任务执行混在一起,出了问题你都不知道是调度器挂了还是执行器崩了。

OLAP 任务调度系统四层架构 接入层(API Gateway) RESTful API / gRPC / WebSocket 调度层(Scheduler Core) DAG 解析 · 依赖管理 · 优先级队列 · 分布式锁 定时触发 · 事件触发 · 重试策略 执行层(Executor Cluster) Worker 节点 · 资源隔离 · 日志采集 · 结果回写 监控层(Monitor & Alert) 指标采集 · 告警推送 · 链路追踪 · 可视化大盘 用户/系统入口 大脑,决策中心 干活的人 眼睛和耳朵

2.3.1 接入层

接入层是系统的门面。用户通过这里提交任务、查看状态。我建议用 RESTful API 作为主要接口,简单通用。如果对实时性要求高(比如实时流任务),可以上 WebSocket 或 gRPC。

  • 任务 CRUD:创建、更新、删除、查询任务
  • 任务操作:暂停、恢复、手动触发、杀死
  • 权限校验:每个请求都要鉴权,防止恶意操作

2.3.2 调度层

这是整个系统的大脑。调度层不负责执行任务,它只负责“决定谁在什么时候该干什么”。

调度层核心职责:

  • DAG 解析:把用户提交的任务依赖图解析成可执行的有向无环图
  • 依赖检查:每个任务执行前,检查它的上游是否全部成功
  • 优先级队列:高优任务插队,低优任务排队
  • 分布式锁:防止同一个任务被多个调度器同时调度(我踩过这个坑)

2.3.3 执行层

执行层就是干活的。它从调度层拿到任务指令,然后真正去跑 SQL、跑脚本、跑 Spark 作业。

我曾经犯过一个错误:让执行层直接连接数据库。结果某个慢 SQL 把连接池打满了,其他任务全部排队。后来我改成每个 Worker 独立管理自己的连接池,问题才解决。

  • Worker 节点:可以水平扩展,每个 Worker 负责执行一个或多个任务
  • 资源隔离:用容器(Docker)或进程级别隔离,防止任务之间互相影响
  • 日志采集:实时把 stdout/stderr 推送到中心日志服务

2.3.4 监控层

没有监控的调度系统,就像闭着眼睛开车。你根本不知道哪个任务挂了、哪个节点宕了。

我的经验:监控层不要只做“事后诸葛亮”。要能做到事前预警。比如某个任务最近 3 天执行时间越来越长,说明数据量在增长,需要提前扩容。

  • 指标采集:任务执行时长、成功率、排队长度、Worker 负载
  • 告警推送:钉钉、企业、邮件、短信(分级告警)
  • 链路追踪:一个任务从提交到执行完成,全链路可追溯
  • 可视化大盘:实时展示系统健康状态

2.4 小结

这一章我们聊了需求梳理、技术选型和四层架构。说白了,架构设计没有标准答案,但分层的思想是通用的。每一层只关心自己的事,层与层之间通过 API 通信。这样后期无论是替换调度算法,还是升级执行引擎,都不会牵一发动全身。