3. 接口契约总览:契约分层架构与版本化策略

GoDAG 调度系统的边界接口契约并非扁平化的单一协议,而是按照职责边界划分为三个清晰的层次:用户层、调度层和执行层。每一层面向不同的调用方,承载不同的语义和约束。同时,契约本身需要具备可演进的版本化能力,以兼容系统升级与接口变更。

3.1 契约分层架构

三层契约的划分依据是调用方与系统模块之间的物理边界和逻辑职责。用户层面向外部业务系统,调度层面向内部编排引擎,执行层面向具体的任务执行器。三者形成自上而下的依赖关系,下层为上层提供能力抽象。

核心原则:每一层契约只对本层的调用方负责,禁止跨层直接调用。用户层契约不感知执行器细节,执行层契约不暴露调度策略。
GoDAG 契约分层架构 用户层契约(User API) 面向:业务系统 / 外部客户端 职责:DAG 定义提交、状态查询、结果回调 协议:gRPC / HTTP REST / 异步消息 调度层契约(Scheduler API) 面向:调度引擎 / 编排组件 职责:任务拓扑解析、依赖排序、资源分配 协议:内部 RPC / 本地函数调用 执行层契约(Executor API) 面向:任务执行器 / Worker 节点 职责:任务启动、状态上报、日志采集 协议:gRPC 双向流 / 共享存储 说明:箭头表示调用方向,上层依赖下层提供的服务抽象。

3.2 各层契约核心要素

每一层契约由一组核心接口和数据结构构成。下表列出各层的关键契约要素及其语义说明:

契约层 核心接口 输入 / 输出 关键约束
用户层 SubmitDAG、GetDAGStatus、CancelDAG DAG 定义 JSON / 状态枚举 + 结果数据 幂等提交、最大 DAG 深度 ≤ 100
调度层 ResolveDependencies、ScheduleTasks 任务拓扑图 / 调度计划 无环保证、资源配额校验
执行层 RunTask、ReportStatus、StreamLogs 任务上下文 / 状态变更事件 超时控制、重试次数 ≤ 3
设计要点:用户层契约应保持稳定,避免频繁变更;调度层和执行层契约可以随内部优化迭代,但必须保证向后兼容。

3.3 契约版本化策略

接口契约的版本化是保障系统演进过程中上下游兼容性的核心手段。GoDAG 采用 语义化版本 + 兼容性矩阵 的双重策略。

3.3.1 版本号规范

每个契约接口的版本号遵循 MAJOR.MINOR.PATCH 格式:

  • MAJOR:不兼容的接口变更(如删除字段、修改必填项)。
  • MINOR:向后兼容的功能新增(如增加可选字段、新增接口)。
  • PATCH:内部修复或文档更新,不涉及接口语义变化。

3.3.2 兼容性矩阵

不同层之间的版本依赖关系通过兼容性矩阵定义,确保调度层和执行层可以独立升级:

调用方版本 被调用方版本 兼容性 说明
用户层 v1.0 调度层 v1.x ✅ 完全兼容 MAJOR 相同,MINOR 可高可低
用户层 v1.0 调度层 v2.0 ❌ 不兼容 需升级用户层或启用适配层
调度层 v2.1 执行层 v2.x ✅ 兼容 MINOR 版本内可互操作
调度层 v2.0 执行层 v1.5 ⚠️ 有条件兼容 需检查具体接口变更日志

3.3.3 版本协商与降级

在运行时,调用方与被调用方通过握手协议协商版本:

// 版本协商请求示例
{
  "caller": "user-service",
  "caller_version": "1.2.0",
  "supported_apis": ["SubmitDAG", "GetDAGStatus"],
  "min_compatible_version": "1.0.0"
}

// 版本协商响应示例
{
  "status": "ok",
  "selected_version": "1.2.0",
  "deprecated_fields": ["callback_url"],
  "upgrade_hint": "v2.0 will remove callback_url, use event_subscription instead"
}
注意:当 MAJOR 版本不匹配时,系统应拒绝调用并返回明确的错误码,避免数据损坏或逻辑错误。建议在网关层统一做版本路由。

3.4 契约分层与版本化的协同关系

分层架构与版本化策略共同构成了 GoDAG 的接口治理基础。下图展示了两者如何协同工作:

契约分层与版本化协同关系 契约分层 用户层 v1.x 稳定,低频变更 调度层 v2.x 迭代中,兼容优先 执行层 v2.x 灵活,支持多版本 版本化策略 语义化版本 MAJOR.MINOR.PATCH 兼容性矩阵 跨层版本映射 版本协商 运行时握手 治理产出 接口变更日志 每个版本记录 适配层代码 版本桥接实现 兼容性测试套件 自动化回归验证

3.5 契约定义示例(用户层)

以下是一个用户层契约的 Protobuf 定义片段,展示了版本化字段和兼容性设计:

syntax = "proto3";
package godag.user.v1;

import "google/protobuf/timestamp.proto";

// DAG 提交请求
message SubmitDAGRequest {
  string dag_id = 1;                    // 必填,全局唯一
  string name = 2;                      // 必填
  repeated TaskNode tasks = 3;          // 必填,任务节点列表
  map<string, string> labels = 4;      // 可选,标签元数据
  // v1.1 新增:任务超时全局配置
  optional int32 global_timeout_seconds = 5;
  // v1.2 新增:事件订阅配置
  repeated EventSubscription subscriptions = 6;
}

message TaskNode {
  string task_id = 1;
  string type = 2;                      // 任务类型
  repeated string depends_on = 3;       // 依赖任务 ID 列表
  bytes payload = 4;                    // 任务参数
}

message EventSubscription {
  string event_type = 1;                // 事件类型
  string callback_url = 2;              // 回调地址
}

message SubmitDAGResponse {
  string dag_id = 1;
  string status = 2;                    // "pending" | "running" | "completed"
  google.protobuf.Timestamp created_at = 3;
}
版本化设计要点:
  • 新增字段使用 optional 修饰,保证旧客户端不传值时仍可正常工作。
  • 枚举值使用开放枚举(允许未知值),避免新增枚举导致反序列化失败。
  • 每个接口文件在 package 路径中标注 MAJOR 版本(如 v1、v2)。

3.6 本章小结