ZACHWANGw / distributed-scheduler

A distributed job scheduler framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Blog License JDK Build status

简体中文 | English

Distributed Scheduler

Introduction

一个分布式的任务调度框架,除了具备常规的分布式任务调度功能外,还提供自定义子任务的拆分、可对执行中的长任务自由控制、DAG任务依赖、管理器与执行器分离部署等能力。

轻量级,简单易用,特别适合长任务的执行。有较好的伸缩性,扩展性,稳定性,历经生产检验。

Architecture

  • 架构图

Architecture

  • 代码结构
distributed-scheduler
├── scheduler-common                                         # 工具包
├── scheduler-core                                           # 任务调度相关的核心类(如数据模型、枚举类、抽象层接口等)
├── scheduler-dispatch                                       # 任务分发模块
│   ├── scheduler-dispatch-api                               # 任务分发的抽象接口层
│   ├── scheduler-dispatch-http                              # 任务分发的Http实现
│   └── scheduler-dispatch-redis                             # 任务分发的Redis实现
├── scheduler-registry                                       # Server(Supervisor & Worker)注册模块
│   ├── scheduler-registry-api                               # Server注册的抽象接口层
│   ├── scheduler-registry-consul                            # Server注册的Consul实现
│   ├── scheduler-registry-nacos                             # Server注册的Nacos实现
│   ├── scheduler-registry-redis                             # Server注册的Redis实现
│   ├── scheduler-registry-etcd                              # Server注册的Etcd实现
│   └── scheduler-registry-zookeeper                         # Server注册的Zookeeper实现
├── scheduler-samples                                        # 使用范例模块
│   ├── scheduler-samples-common                             # 存放使用范例中用到的公共代码,包括使用到的一些公共配置文件等
│   ├── scheduler-samples-merged                             # Supervisor与Worker合并部署的范例(Spring boot应用)
│   └── scheduler-samples-separately                         # Supervisor与Worker分离部署的范例模块
│       ├── scheduler-samples-separately-supervisor          # Supervisor单独部署的范例(Spring boot应用)
│       ├── scheduler-samples-separately-worker-frameless    # Worker单独部署的范例(不依赖Web容器,直接main方法启动)
│       └── scheduler-samples-separately-worker-springboot   # Worker单独部署的范例(Spring boot应用)
├── scheduler-supervisor                                     # Supervisor代码(依赖于Spring Web环境,需要引导Spring扫描该包目录)
└── scheduler-worker                                         # Worker代码

Features

  • 分为管理器(Supervisor)和执行器(Worker)两种角色,Supervisor与Worker可分离部署
  • Supervisor与Worker通过注册中心解耦,目前支持的注册中心有:Redis、Consul、Nacos、Zookeeper、Etcd
  • Supervisor以任务分发方式把任务给到Worker,目前支持的任务分发方式有:Redis、Http
  • 支持任务分组(job-group),任务会分发给指定组的Worker执行
  • 自定义拆分任务,重写JobHandler#split即可把一个大任务拆分为多个小任务,任务分治
  • 提供任务执行快照的自动保存(checkpoint),让执行信息不丢失,保证因异常中断的任务能得到继续执行
  • 提供执行中的任务控制能力,可随时暂停/取消正在执行中的任务,亦可恢复执行被暂停的任务
  • 提供任务依赖执行的能力,多个任务构建好DAG依赖关系后,任务便按既定的依赖顺序依次执行

Download from central

<dependency>
  <groupId>cn.ponfee</groupId>
  <artifactId>scheduler-{xxx}</artifactId>
  <version>1.6</version>
</dependency>

Build from source

./mvnw clean package -DskipTests -Dcheckstyle.skip -U

Quick Start

  1. 运行仓库代码提供的SQL脚本,创建数据库表:db-script/JOB_TABLES_DDL.sql,注:可直接运行内存数据库内置mysql-server

  2. 修改Mysql、Redis、Consul、Nacos、Zookeeper、Etcd等配置文件:scheduler-samples-common/src/main/resources/

  • 如果不使用Redis做注册中心、任务分发及分布式锁,可排除scheduler-common模块下的Maven依赖spring-boot-starter-data-redis
  • 不依赖Web容器的Worker应用的配置文件是在worker-conf.yml
  1. 编写自己的任务处理器PrimeCountJobHandler,并继承JobHandler

  2. 启动scheduler-samples/目录下的各应用,包括:

 1)scheduler-samples-merged                        # Supervisor与Worker合并部署的Spring boot应用
 2)scheduler-samples-separately-supervisor         # Supervisor单独部署的Spring boot应用
 3)scheduler-samples-separately-worker-springboot  # Worker单独部署的Spring boot应用
 4)scheduler-samples-separately-worker-frameless   # Worker单独部署,不依赖Web容器,直接运行Main方法启动
  • 已配置不同端口,可同时启动
  • 可以在开发工具中运行启动类,也可直接运行构建好的jar包
  • 注册中心或任务分发的类型选择是在Spring boot启动类中切换注解
    • EnableRedisServerRegistry启用Redis做为注册中心(内置redis-server)
    • EnableConsulServerRegistry启用Consul做为注册中心(内置consul-server)
    • EnableNacosServerRegistry启用Nacos做为注册中心(内置nacos-server)
    • EnableEtcdServerRegistry启用Etcd做为注册中心(内置etcd-server)
    • EnableZookeeperServerRegistry启用Zookeeper做为注册中心(内置zookeeper-server)
    • EnableRedisTaskDispatching启用Redis做任务分发
    • EnableHttpTaskDispatching启用Http做任务分发
@EnableConfigurationProperties({
    SupervisorProperties.class,
    HttpProperties.class,
    ConsulProperties.class,
    NacosProperties.class,
    ZookeeperProperties.class,
    EtcdProperties.class,
})
@EnableSupervisor
@EnableRedisServerRegistry // EnableRedisServerRegistry、EnableConsulServerRegistry、EnableNacosServerRegistry、EnableZookeeperServerRegistry、EnableEtcdServerRegistry
@EnableRedisTaskDispatching // EnableRedisTaskDispatching、EnableHttpTaskDispatching
@SpringBootApplication(
    exclude = {
        DataSourceAutoConfiguration.class
    },
    scanBasePackages = {
        "cn.ponfee.scheduler.samples.common.configuration",
        "cn.ponfee.scheduler.samples.supervisor.configuration",
        "cn.ponfee.scheduler.supervisor",
    }
)
public class SupervisorApplication {
    public static void main(String[] args) {
        SpringApplication.run(SupervisorApplication.class, args);
    }
}
  1. 执行以下curl命令添加任务(选择任一运行中的Supervisor应用替换localhost:8081)
  • triggerConf修改为大于当前时间的日期值以便即将触发(如当前时间的下一分钟)
  • jobHandler为刚编写的任务处理器类的全限定名(也支持直接贴源代码)
curl --location --request POST 'http://localhost:8081/api/job/add' \
--header 'Content-Type: application/json' \
--data-raw '{
    "jobGroup": "default",
    "jobName": "PrimeCountJobHandler",
    "jobHandler": "cn.ponfee.scheduler.samples.common.handler.PrimeCountJobHandler",
    "jobState": 1,
    "jobParam": "{\"m\":1,\"n\":6000000000,\"blockSize\":100000000,\"parallel\":7}",
    "triggerType": 2,
    "triggerConf": "2022-10-06 12:00:00"
}'
  1. 查询库表验证任务是否添加成功,以及可查看任务的执行信息:
-- 刚CURL添加的任务会落入该表中
SELECT * FROM sched_job;

-- 查看任务的执行信息
SELECT * from sched_track;
SELECT * from sched_task;

-- 可执行以下SQL让该JOB再次触发执行
UPDATE sched_job SET job_state=1, misfire_strategy=3, last_trigger_time=NULL, next_trigger_time=1664944641000 WHERE job_name='PrimeCountJobHandler';
  • 也可执行以下CURL命令手动触发执行(选择一台运行中的Supervisor替换localhost:8081,jobId替换为待触发执行的job)
curl --location --request POST 'http://localhost:8081/api/job/manual_trigger?jobId=4236701614080' \
--header 'Content-Type: application/json'

Contributing

如有发现bug、更优的实现方案、新特性等,可提交PR或新建Issues

Todo List

  • Handler解耦:Handler代码只在Worker服务中,Worker提供处理器校验及拆分任务的接口WorkerRemote
  • 扩展注册中心:Zookeeper、Etcd、Nacos
  • 任务管理后台Web UI、账户体系及权限控制、可视化监控BI
  • 增加多种Checkpoint的支持:File System、Hadoop、RocksDB
  • 本机多网卡时,指定网卡的host ip获取

About

A distributed job scheduler framework

License:Apache License 2.0


Languages

Language:Java 100.0%