3. 任务编排核心概念

在金融场景中,一个日终批处理往往包含行情拉取、估值计算、风险指标生成、对账、报表输出等数十个任务。这些任务并非孤立运行,而是存在明确的先后与依赖关系。任务编排的核心,就是把这些关系用可描述、可调度、可重试的结构表达出来,并交给调度器与执行器落地。本节围绕七个核心概念展开:DAG、工作流、调度器、执行器、依赖解析、并发控制与资源隔离。

一、核心原理:从DAG到执行器

DAG(有向无环图)是任务编排的数学基础。每个节点代表一个任务实例,每条有向边代表依赖方向:A→B 表示 B 必须在 A 成功完成后才能开始。“无环”是关键约束——若存在环,依赖解析将陷入死循环,调度器无法确定任何任务的起始点。金融批处理中常见的“估值→风控→报表”就是典型链式DAG,而“多市场行情并行拉取→汇总→统一估值”则是扇入型DAG。

工作流是DAG的业务化封装,除拓扑结构外,还携带调度周期、重试策略、超时、告警、参数模板等元数据。可以理解为:DAG描述“谁依赖谁”,工作流描述“何时跑、怎么跑、失败怎么办”。

调度器负责在正确的时间点触发工作流,并持续跟踪每个任务实例的状态。它通常维护一张状态表,记录任务从“等待依赖”到“就绪”“运行中”“成功”“失败”“重试中”的迁移。执行器则是真正拉起进程、容器或远程调用的组件,它从调度器领取就绪任务,执行后回写状态与日志。

依赖解析的本质是拓扑排序:调度器周期性扫描所有任务,将“所有上游均为成功”的任务标记为就绪。若上游失败且重试耗尽,下游应被标记为“上游失败”而非“就绪”,避免无效执行。

二、方法流程:一次调度的完整链路

  1. 调度器按周期或事件触发工作流实例,生成任务实例并初始化状态为“等待依赖”。
  2. 依赖解析器读取DAG边关系,计算每个任务的入度;入度为0且上游成功的任务进入就绪队列。
  3. 并发控制器根据工作流级与任务级并发上限,从就绪队列中选取可执行任务。
  4. 资源隔离层为任务分配队列、标签或容器资源,确保高优先级估值任务不被低优先级报表任务挤占。
  5. 执行器拉起任务,采集退出码、耗时与日志;成功则更新状态并触发下一轮依赖解析,失败则进入重试策略。

下面是一段简化的DAG定义与调度参数示例,展示了依赖、重试与资源标签如何同时表达:

workflow: eod_valuation
schedule: "0 18 * * *"
tasks:
  - id: fetch_market_data
    executor: python
    retries: 3
    retry_delay: 60
    resources: {queue: "market", cpu: 2}
  - id: valuation
    depends_on: [fetch_market_data]
    executor: spark
    retries: 1
    resources: {queue: "compute", memory: "16Gi"}
  - id: risk_report
    depends_on: [valuation]
    executor: python
    resources: {queue: "report"}
concurrency:
  workflow_limit: 5
  task_limit: 2

三、案例场景:多市场估值批处理

某券商日终需处理A股、港股、三个市场的行情,再统一估值并生成风控报表。若串行执行,总耗时约90分钟;若不加控制地全部并行,又会因行情接口限流和计算资源争抢导致大量超时。合理的编排方式是:三个行情拉取任务并行,但通过资源隔离限制在“market”队列且总并发不超过3;估值任务依赖三者全部成功,使用独立“compute”队列;报表任务依赖估值,使用“report”队列。这样既缩短了关键路径,又避免了资源冲突。

多市场估值批处理DAG与资源隔离 A股行情拉取 queue: market 港股行情拉取 queue: market 行情拉取 queue: market 统一估值 queue: compute 风控报表 queue: report 并发控制 market队列≤3 compute队列≤2

四、误区与复盘

误区一:把DAG当成流程图。流程图描述“人怎么操作”,DAG描述“任务依赖什么”。若把条件分支、人工审批直接画进DAG边,会导致依赖解析复杂化。正确做法是用任务状态与条件网关表达分支,保持DAG本身无环且语义单一。

误区二:忽视并发控制的粒度。只设工作流级并发,可能导致同一工作流内多个重任务同时抢占资源;只设任务级并发,又可能让多个工作流实例叠加压垮下游。实践中应同时配置工作流级与任务级上限,并为关键队列设置独立配额。

误区三:资源隔离只靠“标签”。标签只是声明,若执行器不按标签路由,隔离形同虚设。必须确保调度器将标签映射到实际队列或容器资源池,并在执行器侧强制校验。

概念 核心职责 金融场景关注点
DAG 描述任务依赖方向与无环约束 估值依赖行情,报表依赖估值
工作流 封装调度周期、重试、告警等元数据 日终批、盘中定时、事件触发
调度器 触发实例、跟踪状态、驱动依赖解析 交易日历、时区、延迟容忍
执行器 拉起任务并回写结果 Python/Spark/Shell多运行时
依赖解析 拓扑排序,判定任务就绪 上游失败时阻断下游
并发控制 限制同时运行的任务数量 接口限流、计算资源配额
资源隔离 按队列/标签分配执行资源 估值与报表互不抢占
复盘时建议重点检查三件事:DAG中是否存在隐式环(如通过动态依赖引入);重试策略是否与幂等性匹配;资源隔离是否在执行器侧真正生效。这三项直接决定失败重试能否安全落地。