AutoJob动态任务调度框架

联合创作 · 2023-09-29

AutoJob是一款轻量级任务调度框架,具有分布式、全异步、易拓展、易集成等特点,提供多种任务调度模式和多种任务类型。配置丰富、拓展方便、使用简单、代码侵入性低。

版本更新

2022-11-22: 初版0.9.1


2022-12-9: 0.9.2

优化API。

核心调度模块停止使用缓存时间戳,解决时间精度低的问题。

重构注解调度器。

重构执行器池,新增基于时间动态调整的线程池封装TimerThreadPoolExecutorHelper

修改已知BUG。

调整项目结构。

2022-12-26: 新增Rest接口:链接: https://www.apifox.cn/apidoc/shared-05120000-4d19-4c75-a7f6-dc56105972cb 访问密码 : autojob

2022-12-27: 优化子任务处理逻辑,新增任务MissFire事件

2022-12-29: 增加多数据库适配,目前支持mysql,postresql

2023-1-3:

优化重试机制,每个任务可单独配置重试逻辑

优化邮件报警机制,每个任务可单独配置邮箱

新增任务重试事件TaskRetryEvent

调度记录表新增is_retry属性,表明该条调度记录是否是由于异常进行重试的调度记录

其他已知BUG


2023-3-14: 0.9.3

内置RPC框架编解码器改为使用ProtoStuff,简化API。

配置支持嵌套配置,内容可以通过VMOptions等给出,保护系统安全。

支持环境变量,便于在测试环境和生产环境切换。见:“四、环境变量”


2023-3-28: 0.9.4

对任务表进行拆分,目前拆分成aj_method_job和aj_script_job便于后期任务类型拓展。 注意0.9.4版本与之前版本的数据库结构不兼容

优化日志处理逻辑,从处理器私有处理线程到loop轮询,避免并发任务过多导致线程资源耗尽。

新增任务运行上下文、任务运行堆栈,便于故障恢复等。具体见“九、任务运行上下文;十一、所有配置”。

新增模板任务,更加优雅地开发任务。具体见:“十二、高级用法-注解任务开发的高级应用-@TemplateAutoJob”。


2023-7-12: 0.9.5

解决日志存在的BUG:日志消息队列不清空的问题。 解决集群部署时重复启动的问题。 新增任务属性:executableMachines,用于指定执行机器,只有地址匹配的机器方可执行。数据库结构有变动(aj_method_job和aj_script_job新增executable_machines列),可以根据SQL脚本自行新增,不要直接执行脚本,否则会造成数据丢失。


2023-7-12: 0.9.6 最新

新增功能:

  • 任务并发运行:同一个任务可以同时运行多个实例。
  • 任务故障转移:重试策略新增故障转移策略,在开启集群模式时有效,异常的任务会选择一个“较好的”节点进行故障转移执行。
  • 任务动态分片:在集群模式下支持分片任务,节点会自动感知当前集群节点数目,根据集群情况动态分片。
  • 任务保存策略:支持不存在时保存、创建一个新的版本、存在则更新策略。
  • 注解式脚本任务:可以直接在一个Java方法上使用@ScriptJob注解来定义一个脚本任务,支持动态命令行。
  • 函数任务:可以非常简单的将一些业务逻辑交由AutoJob管理,AutoJob会为这些业务逻辑提供故障重试、过长中断、日志存储的功能。

其他性能优化和BUG解决。

更新说明:

本次更新涉及数据库结构变动,需要重新执行SQL脚本,请先备份数据。

一、背景

生活中,业务上我们会碰到很多有关作业调度的场景,如每周五十二点发放优惠券、或者每天凌晨进行缓存预热、亦或每月定期从第三方系统抽数等等,Spring和java目前也有原生的定时任务支持,但是其都存在一些弊病,如下:

  • 不支持集群,未避免任务重复执行的问题
  • 不支持生命周期的统一管理
  • 不支持分片任务:处理有序数据时,多机器分片执行任务处理不同数据
  • 不支持失败重试:出现异常任务终结,不能根据执行状态控制任务重新执行
  • 不能很好的和企业系统集成,如不能很好的和企业系统前端集成以及不能很好的嵌入到后端服务
  • 不支持动态调整:不重启服务情况下不能修改任务参数
  • 无报警机制:任务失败之后没有报警通知(邮箱、短信)
  • 无良好的执行日志和调度日志跟踪

基于原生定时任务的这些弊病,AutoJob就由此诞生,AutoJob为解决分布式作业调度提供了新的思路和解决方案。

二、特性

简单: 简单包括集成简单、开发简单和使用简单。

集成简单:框架能非常简单的集成到Spring项目和非Spring项目,得益于AutoJob不依赖于Spring容器环境和MyBatis环境,你无需为了使用该框架还得搭建一套Spring应用。

开发简单:AutoJob开发初衷就希望具有低代码侵入性和快速开发的特点,如下在任意一个类中,你只需要在某个需要调度的任务上加上注解,该任务就会被框架进行动态调度:

	@AutoJob(attributes = "{'我爱你,心连心',12.5,12,true}", cronExpression = "5/7 * * * * ?")
    public void formatAttributes(String string, Double decimal, Integer num, Boolean flag) {
        //参数注入
        AutoJobLogHelper logger = new AutoJobLogHelper();//使用框架内置的日志类
        logger.setSlf4jProxy(log);//对Slf4j的log进行代理,日志输出将会使用Slf4j输出
        logger.info("string={}", string);
        logger.warn("decimal={}", decimal);
        logger.debug("num={}", num);
        logger.error("flag={}", flag);
        //使用mapper
        mapper.selectById(21312L);
        //...
    }

使用简单:使用该框架你无需关注太多的配置,整个框架的启动只需要一行代码,如下:

//配置任务扫描包路径
@AutoJobScan({"com.yourpackage"})
//处理器自动扫描
@AutoJobProcessorScan({"com.yourpackage"})
public class AutoJobMainApplication {
    public static void main(String[] args) {
    //框架启动
    	new AutoJobBootstrap(AutoJobMainApplication.class)
                .build()
                .run();
        System.out.println("==================================>系统创建完成");
 	}

}

得益于良好的系统架构和编码设计,你的应用启动无需过多配置,只需要一行代码

动态: 框架提供API,支持任务的动态CURD操作,即时生效。

多数据库支持: 提供多类型数据库支持,目前支持MySQL、PostgreSQL、Oracle、DamengSQL,理论支持SQL标准的所有数据库。

任务依赖: 支持配置子任务,当父任务执行结束且执行成功后将会主动触发一次子任务的执行。

一致性: 框架使用DB乐观锁实现任务的一致性,在集群模式下,调度器在调度任务前都会尝试获取锁,获取锁成功后才会进行该任务的调度。

HA(新): 该框架支持去中心化的集群部署,集群节点通过RPC加密通信。集群节点之间会自动进行故障转移。

弹性增缩容(新): 支持节点的动态上下线,同时节点支持开启保护模式,防止恶劣的网络环境下节点脱离集群。

任务失败重试(新): 支持故障转移和本地重试。

完整的生命周期: 框架提供任务完整的生命周期事件,业务可捕捉并做对应的处理。

动态调度线程池: 框架使用自研的动态线程池,可灵活根据任务流量动态调整线程池核心线程和最大线程参数,节省系统线程资源,并且提供了默认的拒绝处理器,防止任务被missFire。

异步非阻塞的日志处理: 日志采用生产者消费者模型,基于自研的内存消息队列,任务方法作为日志的生产者,生产日志放入消息队列,框架启动对应的日志消费线程进行日志处理。

实时日志: 日志将会实时的进行保存,便于跟踪。

任务白名单: 提供任务白名单功能,只有在白名单中的任务才允许被注册和调度,保证系统安全。

可拓展的日志存储策略: 日志支持多种策略保存,如内存Cache、数据库等,可根据项目需要灵活增加保存策略,如Redis、文件等。

丰富的调度机制: 支持Cron like表达式,repeat-cycle调度、子任务触发、延迟触发等,得益于良好的编码设计,用户可非常简单的新增自定义调度器,如下:

/**
 * 你的自定义调度器
 * @Author Huang Yongxiang
 * @Date 2022/08/18 14:56
 */
public class YourScheduler extends AbstractScheduler{
    public YourScheduler(AutoJobTaskExecutorPool executorPool, IAutoJobRegister register, AutoJobConfigHolder configHolder) {
        super(executorPool, register, configHolder);
    }
    
    //...调度逻辑
}

@AutoJobScan("com.example.autojob.job")
@AutoJobProcessorScan("com.example.autojob")
public class AutoJobMainApplication {
    public static void main(String[] args) {
        new AutoJobLauncherBuilder(AutoJobMainApplication.class)
                .withAutoScanProcessor()
            	//配置你的调度器
                .addScheduler(YourScheduler.class)
                .build()
                .run();
        System.out.println("==================================>系统创建完成");
    }
}

任务报警: 框架支持邮件报警,目前原生支持QQ邮箱、163邮箱、GMail等,同时也支持自定义的邮箱smtp服务器。

1668580284754

目前系统提供:任务失败报警、任务被拒报警、节点开启保护模式报警、节点关闭保护模式报警,当然用户也可非常简单的进行邮件报警的拓展。

丰富的任务入参: 框架支持基础的数据类型和对象类型的任务入参,如Boolean,String,Long,Integer,Double等类型,对于对象入参,框架默认使用JSON进行序列化入参。

良好的前端集成性: 框架提供相关API,用户可以灵活开发Restful接口接入到企业项目,无需额外占用一个进程或机器来单独运行调度中心。

内存任务: 框架提供DB任务和内存任务两种类型,DB任务持久化到数据库,声明周期在数据库内记录,内存任务除了日志,整个生命周期都在内存中完成,相比DB任务具有无锁、调度快速的特点。

脚本任务: 提供脚本任务的执行,如Python、Shell,SQL等。

动态分片(新): 集群模式下框架支持任务分片,多机运行。

全异步: 任务调度流程采用全异步实现,如异步调度、异步执行、异步日志等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行。

浏览 3
点赞
评论
收藏
分享

手机扫一扫分享

编辑
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑
举报