我们知道目前java主流的三大定时任务框架有:Quartz、xxl-job(分布式)、elastic-job(分布式)(单机定时任务:Timer,ScheduledExecutorService,Spring Task)。
Quartz
Spring Boot中的定时器Quartz是一种基于Java的开源调度框架,可以用于在指定时间执行任务或在指定时间间隔内重复执行任务。
它提供了丰富的API和灵活的配置选项,可以满足各种不同的调度需求。在Spring Boot中,可以通过简单的配置和注解来使用Quartz定时器,使得任务调度变得更加简单和方便。
xxl-job
xxl-job是一个国内开源的分布式任务调度平台,提供了任务调度、任务执行、任务监控、报警等功能,支持分布式部署,适用于大规模分布式任务调度场景。
elastic-job
elastic-job是一个国内开源的分布式任务调度框架,提供了分布式任务调度、分布式数据流处理、分布式数据分片等功能,支持多种任务类型,适用于大规模分布式任务调度和数据处理场景。
三者各自的优缺点是什么?
Quartz
优点:支持集群部署
缺点:没有自带的管理界面;调度逻辑和执行任务耦合在一起;维护需要重启服务
总结:针对目前项目情况,利弊相同
xxl-job
优点:支持集群部署;提供运维界面维护成本小;自带错误预警;相对elastic-job来说不需要额外的组件(zookeeper);支持调度策略;支持分片;故障转移 ;更适合分布式
缺点:相对Quartz来说需要多部署调度中心; 仅支持MySQL,使用其他DB需要自己魔改代码
总结:针对目前项目情况,利大于弊
elastic-job
优点:支持集群部署;维护成本小
缺点:elastic-job需要zookeeper,zookeeper集群高可用至少需要三台服务器
总结:针对目前项目情况,弊大于利
就目前三大定时任务框架的缺点和目前项目的状况而言,还是建议选用xxl-job。下面重点聊一下xxl-job。xxl-job结构图:
xxl-job的组成角色:
-
调度中心 : 将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求
-
执行器(触发器): 将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑
-
任务: 具体执行的逻辑代码
“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性。
xxl-job框架的使用步骤:
-
在XXL-job平台上创建任务,并设置任务的执行时间和执行频率。
-
在Java应用程序中引入XXL-job客户端依赖,编写任务执行逻辑。
-
在Java应用程序中创建JobHandler类,实现IJobHandler接口,并实现execute方法,该方法中编写任务执行逻辑。
-
在Java应用程序中创建JobHandlerRegistry类,注册JobHandler类。
-
在Java应用程序中创建XxlJobSpringExecutor类,启动任务调度器。
xxl-job的一些特点:
-
动态:支持动态修改任务状态、启动 / 停止任务,以及终止运行中任务,即时生效;
-
弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
-
路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性 HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
-
阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
-
任务进度监控:支持实时监控任务进度;
-
运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
-
线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入 “Slow” 线程池,避免耗尽调度线程,提高系统稳定性;
-
全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行
从上图可以看出,XXL-JOB
由 调度中心 和 执行器 两大部分组成。调度中心主要负责任务管理、执行器管理以及日志管理。执行器主要是接收调度信号并处理。另外,调度中心进行任务调度时,是通过自研 RPC 来实现的。
不同于 Elastic-Job
的去中心化设计, XXL-JOB
的这种设计也被称为中心化设计(调度中心调度多个执行器执行任务)。
和 Quzrtz
类似 XXL-JOB
也是基于数据库锁调度任务,存在性能瓶颈。不过,一般在任务量不是特别大的情况下,没有什么影响的,可以满足绝大部分公司的要求。
不要被 XXL-JOB
的架构图给吓着了,实际上,我们要用 XXL-JOB
的话,只需要重写 IJobHandler
自定义任务执行逻辑就可以了,非常易用!
@JobHandler(value="myApiJobHandler")
@Component
public class MyApiJobHandler extends IJobHandler {
@Override
public ReturnT<String> execute(String param) throws Exception {
//......
return ReturnT.SUCCESS;
}
}
还可以直接基于注解定义任务。
@XxlJob("myAnnotationJobHandler")
public ReturnT<String> myAnnotationJobHandler(String param) throws Exception {
//......
return ReturnT.SUCCESS;
}