聊聊几种并发调度框架 wip

见识过好多并发调度框架,有DAG编排任务的、有分层编排的、也有仅简单封装go func() {}的。年少时,热衷于研究各个框架的调度原理,分析其原理优劣和实现优雅。自己也尝试创新,并在「导购商卡信息摘要平台」中实践落地了一套。

然而到年纪后,愈发感觉到,并发调度框架应该更加注重:使用者的方便易用、调度内核的逻辑简单和能力丰富、框架的扩展性和SRE支持。可能其调度原理更偏向于"满足需求、能用就行"。当然,框架的性能也不可以被忽视,应用新框架或编写新框架都需要被压测证明,比如即便都是实现了DAG调度编排能力,但不同框架能承接的QPS也是不同的。

下面我来介绍下接触过的几个并发调度框架,聊聊他们的调度实现原理和相关的拓展能力。

调度原理

套路1: 运行时识别依赖并阻塞

调度原理

以两个有依赖关系的执行单元为例,如下图executor1和executor2,分别为被依赖方和有依赖方(有依赖方 依赖了 被依赖方的结果,executor2依赖executor1)。有依赖方获取被依赖方数据时,若被依赖方未执行完成,则有依赖方进行阻塞等待。由此,在运行时动态地按诉求串联起每个执行节点(执行的先后顺序),生成类拓扑图。

注意的是,运行执行单元executor、阻塞等待其他执行单元结果、阻塞结束通知等逻辑,都收由manager进行管理。manager可以认为是框架逻辑,执行单元executor内的代码和依赖什么数据是自定义的业务逻辑。

  • 编排的关键点在于「阻塞」,实施阻塞的逻辑对应图中:

    • 2.每个执行单元均会分配一个无缓冲区channel

    • 4.1 执行单元executor2去获取executor1的结果时,需要先判断executor1.channel,于是实施阻塞

    • 4.2 executor1执行完成后close(channel1)并设置result1,于是executor2解除阻塞并获取executor1结果result1

go 复制代码
func (*JobMgr) GetResult(job) (interface{}, error) {
        c, _ := jobMgr.getJobChanSafely(job)
        if c == nil {
                return nil, ERR_JOBS_UNKNOW_NAME
        }
        <-c // will block here until job is finished
        jobData := jobMgr.getJobData(job)
        return jobData.result, jobData.err
}

func (*JobMgr) run(ctx context.Context) error {
    for finishedCount < len(jobMgr.jobs) {
        select {
        case job := <-jobMgr.indexChan:
              jobMgr.closeChan(jobMgr.getJobChan(job))
              finishedCount += 1
    .......
}
  • 为什么说是类拓扑图?

    • 全部执行器是同时触发开始运行的,而非executor1执行完成再运行executor2。因此从调用时间和span看有依赖方,它是包含被依赖方的。
  • 为什么说是动态?

    • 在运行时、执行到"获取其他执行器result"代码时,才可以分析出两者属于串行关系
    • 由于实施阻塞的灵活性,即便有"获取其他执行器result"的代码,也可以通过超时控制、条件判断等逻辑跳过某次依赖

拓展能力

  • 该套路的优点

    • 实施阻塞的灵活性非常强,可在运行时动态控制。例如在条件1时executor2依赖executor1,在条件2时executor2不依赖executor1。
    • 执行器中可灵活自定义强弱依赖关系
    • 隐式依赖管理
  • 该套路的缺点

    • 没办法前置进行依赖死循环检查
    • 执行器编码需要遵守接口规范/模版

具体框架

jobmgr框架

srv_flow框架

summary loader

wip 套路2: 通过函数出度入度预生成拓扑图

wip 套路3: 手动分层顺序执行

拓展能力

调度框架除了核心的任务编排能力外,也会提供各种拓展能力,例如埋点监控、稳定性SRE。上文有顺便提到不同框架所提供的拓展能力。其他我能想到常见能力有:

  • panic recover

  • 错误处理和表达

  • 超时控制和通知

    • 整体流程的超时
    • 执行单元的超时
  • 强弱依赖

  • DAG调度图可视化

  • 耗时监控

    • 某次请求时,各个节点的耗时
    • 每个节点的耗时metrics
相关推荐
吳所畏惧5 小时前
Linux环境/麒麟V10SP3下离线安装Redis、修改默认密码并设置Redis开机自启动
linux·运维·服务器·redis·中间件·架构·ssh
盖世英雄酱581365 小时前
Java 组长年终总结:靠 AI 提效 50%,25 年搞副业只赚 4k?
后端·程序员·trae
会周易的程序员5 小时前
多模态AI 基于工业级编译技术的PLC数据结构解析与映射工具
数据结构·c++·人工智能·单例模式·信息可视化·架构
+VX:Fegn08955 小时前
计算机毕业设计|基于springboot + vue在线音乐播放系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
code bean6 小时前
Flask图片服务在不同网络接口下的路径解析问题及解决方案
后端·python·flask
零售ERP菜鸟6 小时前
当业务战略摇摆不定:在变化中锚定不变的IT架构之道
信息可视化·职场和发展·架构·创业创新·学习方法·业界资讯
+VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
努力的小郑6 小时前
2025年度总结:当我在 Cursor 里敲下 Tab 的那一刻,我知道时代变了
前端·后端·ai编程
MinggeQingchun6 小时前
业务架构、产品架构、应用架构、数据架构、技术架构和项目架构
架构
乾元7 小时前
ISP 级别的异常洪泛检测与防护——大流量事件的 AI 自动识别与响应工程
运维·网络·人工智能·安全·web安全·架构