JobFlow已开源:面向业务中台的轻量级分布式调度引擎 — 支持动态分片与延时队列

📖 项目简介

JobFlow 是面向业务中台的轻量级、高性能分布式调度引擎,专为 Nacos 体系打造,在不引入任何新中间件的前提下,将任务调度、动态分片和延时队列能力内建到微服务架构之中。

🔗 开源地址与系列文章

✨ 核心功能

1. 调度中台化:调度即业务

设计理念:

  • 调度器不是一个独立的"平台",而是业务中台的一部分
  • 不需要额外的管理后台,直接通过数据库和配置文件管理
  • 复用现有的监控、日志、服务发现体系

与传统方案对比:

维度 传统调度平台 JobFlow 中台化
定位 独立的调度平台 业务中台的一部分
管理方式 Web 管理后台 数据库 + 配置文件
运维团队 需要专门运维 业务团队自己维护
监控日志 需要单独接入 复用现有体系
服务发现 自建注册中心 复用 Nacos

核心价值:

  • 零额外运维成本:就是一个普通的 Spring Boot 微服务
  • 低学习成本:复用现有技术栈,无需学习新平台
  • 高集成度:与业务中台紧密集成,不是"外部系统"

2. 分片调度机制(核心亮点)

为什么需要分片?

当处理大数据量任务时(如给 100 万用户发送通知),单实例执行需要很长时间。分片可以:

  • 将大任务拆分成多个小任务
  • 多个执行器并行处理
  • 显著缩短总执行时间

JobFlow 的分片设计:

ini 复制代码
父子记录结构:
- 父记录(job_execution):记录整体任务信息
- 子记录(job_sub_execution):每个分片的执行记录

回调驱动动态分配:
1. 调度器触发任务,创建父子记录
2. 初始分配 min(n, m) 个分片
   - n = 执行器实例数
   - m = 配置的分片数
3. 执行器完成分片后回调调度器
4. 调度器动态分配下一个 PENDING 分片
5. 循环直到所有分片完成

乐观锁 CAS 抢占:
- 多个执行器同时回调时,通过 CAS 更新抢占分片
- WHERE id = ? AND status = 'PENDING' AND version = ?
- 只有一个执行器能抢到,其他自动重试

优势对比:

特性 传统静态分片 JobFlow 动态分片
分片分配 调度时一次分配完 回调驱动动态分配
负载均衡 不均衡(慢实例卡住) 自动均衡(快实例多处理)
实例变化 需要重新调度 自动适应
并发控制 固定并发数 动态并发(根据实际负载)

3. 延时队列(独立设计)

  • 一次性延时任务:支持任意时间后执行的延时任务
  • 业务参数透传:通过 JSON Payload 传递业务参数
  • 指数退避重试:失败后自动重试(3分钟 → 5分钟,最多3次)
  • 幂等性保证:基于 bizUuid 的唯一约束,防止重复提交

4. 高可用保障

  • 无锁调度:Hash 分区 + Owner 判定,避免分布式锁
  • 超时巡检:自动检测并标记超时任务
  • 分片补偿:PENDING/RUNNING 超时分片自动重试
  • 低频漏调检测:小时级任务的漏调自动补偿

5. 可观测性

  • 全链路 TraceId:从调度器到执行器的完整链路追踪
  • 详细日志:关键节点的完整日志记录
  • 状态可查:数据库状态实时可查,便于问题排查

🆚 与 XXL-Job 对比

特性 JobFlow XXL-Job
服务发现 ✅ 复用 Nacos ❌ 独立实现(手动注册)
依赖中间件 仅需 MySQL + Nacos MySQL + 独立调度中心
分片策略 动态回调驱动 + 乐观锁 CAS 静态分配(调度时确定)
延时队列 ✅ 原生支持(独立设计) ❌ 不支持
无锁调度 ✅ Hash 分区 需要分布式锁
低频补偿 ✅ 自动检测小时级任务漏调 ❌ 不支持
架构复杂度 轻量级(无调度中心 UI) 重量级(包含完整管理后台)
学习成本 低(复用 Spring Boot 生态) 中等

🎯 设计理念

1. 复用优于重造

  • Nacos 服务发现:不重复造轮子,直接复用微服务基础设施
  • HTTP 调用:复用 Spring Boot Web 能力,无需自定义协议
  • 统一注解 :周期任务和延时任务共享 @JobHandler 注解

2. 关注点分离

  • Cron 层抽象 :所有定时任务统一由 CronTasks 触发,业务逻辑在 Service 层
  • 独立表设计 :延时任务使用独立的 job_delay_task 表,与周期任务解耦
  • 职责单一:每个模块专注于自己的核心职责

3. 高性价比容错

  • 数据库兜底:通过唯一索引防止重复调度,无需分布式锁
  • CAS 乐观锁:分片抢占使用数据库 CAS,简单可靠
  • 指数退避:失败重试采用指数退避,避免雪崩

4. 轻量级优先

  • 无 UI 管理后台:通过配置文件和数据库管理任务,降低运维成本
  • 最小依赖:只依赖 Spring Boot、MySQL、Nacos
  • 简单部署:调度器和执行器都是标准的 Spring Boot 应用

🏗️ 架构设计

scss 复制代码
┌─────────────────────────────────────────────────────────┐
│                    Nacos 服务发现                        │
└─────────────────────────────────────────────────────────┘
           ↓                              ↓
┌──────────────────────┐      ┌──────────────────────┐
│  JobFlow Scheduler   │      │  业务微服务集群       │
│  (调度中台)          │      │  (执行器)            │
│                      │      │                      │
│  - CronTasks         │─────→│  - @JobHandler       │
│  - JobScheduler      │      │  - JobExecutor       │
│  - DelayTaskService  │      │  - 业务逻辑          │
│  - 巡检补偿          │←─────│  - 状态回调          │
└──────────────────────┘      └──────────────────────┘
           ↓
┌──────────────────────┐
│   MySQL 数据库        │
│  - job_definition    │
│  - job_execution     │
│  - job_sub_execution │
│  - job_delay_task    │
└──────────────────────┘

🚀 快速开始

1. 环境准备

  • JDK 17+
  • Maven 3.6+
  • MySQL 8.0+
  • Nacos 2.x

2. 初始化数据库

sql 复制代码
-- 执行 SQL 脚本
source job-flow.sql

3. 启动调度器

bash 复制代码
cd jobflow-scheduler
mvn spring-boot:run

4. 业务服务集成

引入依赖:

xml 复制代码
<dependency>
    <groupId>com.surfing.jobflow</groupId>
    <artifactId>jobflow-client</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

启用 JobFlow:

java 复制代码
@SpringBootApplication
@EnableJobFlow
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

编写任务处理器:

java 复制代码
@Component
@JobHandler("demoJob")
public class DemoJobHandler implements IJobHandler {
    
    @Override
    public JobResult execute(JobContext context) {
        int shardStart = context.getShardStart();
        int shardEnd = context.getShardEnd();
        
        // 业务逻辑
        log.info("执行分片任务,范围:{}-{}", shardStart, shardEnd);
        
        return JobResult.success("任务执行成功");
    }
}

5. 配置任务

在数据库中插入任务定义:

sql 复制代码
INSERT INTO job_definition (
    name, service_name, handler, cron, enabled, shard_count
) VALUES (
    'demoJob', 'user-service-example', 'demoJob', 
    '*/10 * * * * ?', 1, 3
);

📊 核心表设计

job_definition - 任务定义

sql 复制代码
id, name, service_name, handler, cron, enabled,
shard_count, shard_strategy, timeout_seconds, max_retry

job_execution - 执行记录(父记录)

sql 复制代码
id, job_name, trace_id, trigger_time, status, 
shard_total, finish_time

job_sub_execution - 分片执行(子记录)

sql 复制代码
id, parent_execution_id, shard_index, status, 
executor_instance, retry_count, start_time, finish_time

job_delay_task - 延时任务

sql 复制代码
id, trace_id, biz_uuid, service_name, handler,
execute_time, next_attempt_time, payload_json, 
status, retry_count, max_retry

🎯 适用场景

✅ 适合使用 JobFlow

  • 微服务架构:已使用 Nacos 的项目,零额外依赖成本
  • 周期性批处理:数据同步、报表生成、定时清理
  • 延时任务:订单超时取消、临时权限到期、延迟通知
  • 分片并行:大数据量的分片处理(用户推送、数据迁移)

❌ 不适合使用 JobFlow

  • 需要 UI 管理后台:JobFlow 专注于轻量级,暂未提供 Web 管理界面
  • 秒级延时精度:延时队列扫描周期为5秒,不适合毫秒级要求
  • 海量任务:单表百万级以下任务量,超大规模需要分库分表

🔧 配置参数

yaml 复制代码
jobflow:
  scheduler:
    # 任务扫描周期(毫秒)
    poll-interval-ms: 5000
    
    # 分片巡检周期(毫秒,3分钟)
    inspect-interval-ms: 180000
    
    # 低频任务巡检周期(毫秒,10分钟)
    low-frequency-inspect-interval-ms: 600000
    
    # 延时任务扫描周期(毫秒,5秒)
    delay-inspect-interval-ms: 5000
    
    # 默认超时阈值(分钟)
    timeout-threshold-minutes: 10

Author: 踏浪无痕
Last Updated: 2025-12-21

相关推荐
Pitayafruit2 小时前
Spring AI 进阶之路05:集成 MCP 协议实现工具调用
spring boot·后端·llm
ss2732 小时前
线程池:任务队列、工作线程与生命周期管理
java·后端
不像程序员的程序媛2 小时前
Spring的cacheEvict
java·后端·spring
踏浪无痕3 小时前
JobFlow 实战:无锁调度是怎么做到的
后端·面试·架构
shoubepatien3 小时前
JAVA -- 11
java·后端·intellij-idea
豆豆3 小时前
开源企业网站源码免费网站源码. 网站源码下载
开源·cms·单点登录·网站源码·网页源码·源码建站·低代码品平台
喵个咪3 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:kratos-bootstrap 入门教程(类比 Spring Boot)
后端·微服务·go
uzong3 小时前
从大厂毕业后,到小公司当管理,十年互联网老兵的思维习惯阶段复盘
后端
脑极体3 小时前
我即洪流:中国开源三十年
开源