📖 项目简介
JobFlow 是面向业务中台的轻量级、高性能分布式调度引擎,专为 Nacos 体系打造,在不引入任何新中间件的前提下,将任务调度、动态分片和延时队列能力内建到微服务架构之中。
🔗 开源地址与系列文章
- 开源地址 :
https://gitee.com/sh_wangwanbao/job-flow - 系列文章:
- 第一篇:基于Nacos的轻量任务调度方案 ------ 从 XXL-Job 的痛点说起
- 第二篇:JobFlow 实现方案:云原生时代的任务调度新思路
- 第三篇:JobFlow 实战:无锁调度是怎么做到的
- 第四篇:分布式调度的终极难题:超时、补偿与漏调(统写中)
- 第五篇:延时队列的设计与实现(统写中)
✨ 核心功能
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