Dagor —— 一个高性能 DAG 算子执行框架,开箱即用!

Dagor 是一个高性能DAG算子执行框架,专为高并发在线服务设计。它将复杂的业务逻辑解耦为独立的算子,通过DAG进行灵活编排,自动处理并行调度与数据注入。

GitHub 项目地址:
github.com/wwz16/dagor

中文 README:
github.com/wwz16/dagor...


一、背景:复杂在线逻辑,真的只能写 if-else 吗?

复杂业务的在线系统中,我们经常会遇到这样的业务形态:

  • 请求链路长
  • 逻辑复杂、阶段多
  • 不同模块之间存在明确的数据依赖
  • 希望尽可能 并行执行,降低整体 latency

最初的实现通常是这样:

css 复制代码
a := stepA()
b := stepB(a)
c := stepC(a)
d := stepD(b, c)

随着业务增长,很快就会变成:

  • 强耦合
  • 难以重构
  • 不好做并行
  • 难以配置化、AB 实验成本高

在字节 / 阿里 / 腾讯内部,这类问题几乎都会收敛到一个解法

用 DAG(有向无环图)来描述业务执行流程

于是我在业余时间,把这一类"内部 DAG 执行引擎"的设计思想,抽象并实现成了一个 Go 语言开源项目 ------ Dagor


二、Dagor 是什么?

Dagor 是一个基于 DAG 的算子执行框架(Operator-based DAG Engine)

它的核心思想是:

  • 把业务逻辑拆成 Operator(算子)

  • DAG 描述算子之间的数据依赖

  • 由引擎自动完成:

    • 任务调度
    • 并行执行
    • 数据注入
    • 数据传递

一句话总结:

Dagor 让你用「配置」描述业务拓扑,用「代码」实现单点业务逻辑。


三、核心设计理念

1️⃣ 数据驱动,而不是流程驱动

在 Dagor 中,你不需要写「谁先执行谁」:

css 复制代码
"inputs": {
  "a": "n1",
  "b": "n2"
}

只要声明 数据从哪里来,引擎就会自动推导依赖关系。


2️⃣ 字段级依赖,而不是节点级依赖

Dagor 的依赖粒度是 字段(field) ,而不是整节点:

  • 一个算子可以产出多个字段
  • 不同下游节点可以依赖不同字段
  • 并行度最大化

3️⃣ Operator 池化可复用

  • 算子支持 池化(operator pooling)
  • 参数在运行期绑定
  • 自动 Reset,安全复用
  • 大幅降低 GC 压力

四、核心概念速览

概念 说明
Operator 独立的业务计算单元
Vertex 图中的节点,对应一个 Operator
Edge 数据依赖关系
Graph 业务拓扑(DAG)
Engine 图的运行时,负责任务调度

关系示意图:


五、一个最简单但有代表性的示例

1️⃣ 定义算子

go 复制代码
type AddOp struct {
    a   *int `dag:"input"`
    b   *int `dag:"input"`
    sum int  `dag:"output"`
}

func (op *AddOp) Run(ctx context.Context) error {
    op.sum = *op.a + *op.b
    return nil
}

无需手动接线,输入输出由框架自动注入。


2️⃣ 用 JSON 描述业务 DAG

css 复制代码
{
  "name": "math_demo",
  "vertices": {
    "const10": {
      "op": "ConstOp",
      "params": { "in": 10 },
      "outputs": { "out": "n1" }
    },
    "const20": {
      "op": "ConstOp",
      "params": { "in": 20 },
      "outputs": { "out": "n2" }
    },
    "add": {
      "op": "AddOp",
      "inputs": {
        "a": "n1",
        "b": "n2"
      },
      "outputs": {
        "sum": "answer"
      }
    }
  }
}

3️⃣ 运行 DAG

css 复制代码
eng, _ := dagor.NewEngine(graph, pool)
_ = eng.Run(ctx)

v, _ := eng.GetOutput("answer")
fmt.Println(*v.(*int))

六、为什么不用现成的 Workflow / Airflow?

Dagor 的定位很明确:

❌ 不做离线

❌ 不做大而全

❌ 不做跨系统编排

它专注解决的是:

高并发在线请求内的复杂逻辑调度问题

和很多公司内部推荐 / 搜索 / 广告 DAG 引擎的定位是一致的。


七、还有哪些工程化能力?

  • ✅ Operator 自动代码生成,减少手动代码编写
  • ✅ 算子参数 Params开箱即用,无需提前定义结构体,支持路径访问(a.b.c.0
  • ✅ 并行调度 + goroutine pool
  • ✅ 图的超时控制
  • ✅ 图可视化工具

八、适合哪些人?

如果你是:

  • Go 后端工程师
  • 复杂业务流程编排
  • 搜索 / 推荐 / 广告方向
  • 对架构、执行引擎、Infra 感兴趣
  • 想看 "字节/阿里/腾讯内部系统的简化版实现"

那这个项目可能对你有参考价值。


九、项目地址 & 结语

👉 GitHub:
github.com/wwz16/dagor

👉 中文 README:
github.com/wwz16/dagor...

如果你对 DAG / 执行引擎 / 推荐系统架构 感兴趣,也欢迎在评论区交流 👋

相关推荐
stark张宇20 小时前
Go语言核心三剑客:数组、切片与结构体使用指南
后端·go
Aevget20 小时前
智能高效Go开发工具GoLand v2025.3全新上线——新增资源泄漏分析
开发语言·ide·后端·golang·go
源代码•宸1 天前
goframe框架签到系统项目开发(补签逻辑实现、编写Lua脚本实现断签提醒功能、简历示例)
数据库·后端·中间件·go·lua·跨域·refreshtoken
光头闪亮亮2 天前
Go语言开发的命令行MP3播放器
go
Grassto2 天前
Go Module 的版本选择算法:Minimal Version Selection(MVS)
后端·golang·go·go module
汪小成3 天前
Go CLI 入口设计:参数解析、错误处理与项目分层实战
后端·go
gitboyzcf3 天前
Go(GoLang)语言基础、知识速查
后端·go
汪小成4 天前
Go 项目结构总是写乱?这个 50 行代码的 Demo 教你标准姿势
后端·go
littleschemer4 天前
go结构体扫描
游戏·go·解析·struct