Quartz设计原理详解(多图)

定时任务是日常开发中非常常见的功能。

对于简单的任务处理Spring的@Scheduled非常好用。
如果处理更复杂的情况,比如需要宕机恢复或者集群调度,那么Quartz是个不错的轻量级方案。
一些重量级的第三方任务调度系统也是基于Quartz扩展的,比如XXL-JOB

Quartz的模块

Quartz模块.png
  • Trigger定义了何时触发任务,主要是两种SimpleTrigger和CronTigger,其他Tigger基本都可以通过这两种实现。Trigger还可以定义错过的任务如何处理。下表是说明:


    trigger.jpeg
  • Calendar与Trigger相反,Calendar定义哪些时间是特例,不能执行任务。Calendar的优先级高于Trigger。HolidayCalendar比较常用,定义了哪些节日是特殊情况。


    calendar.jpeg
  • Job 负责定义任务所处理的逻辑,实现类需要实现org.quartz.Job接口

public interface Job {
    void execute(JobExecutionContext context) throws JobExecutionException;
}
  • 通过抛出JobExecutionException可以强制控制任务后续处理
public class JobExecutionException extends SchedulerException {
    private boolean refire = false;//true: 重新执行任务(不会触发下一次)
    private boolean unscheduleTrigg = false;//true: 直接标记Trigger完成
    private boolean unscheduleAllTriggs = false;//true: 直接标记所有和Job相关的Trigger都已经完成
}
  • Stateful Job。不同于一般的无状态任务,可以同时执行。有状态任务不能同时执行,而且需要保存状态。根据需要给可以Job类添加@PersistJobDataAfterExecution 或 @DisallowConcurrentExecution
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public interface StatefulJob extends Job {
}
  • JobDetail 保存Job的元信息,包括类定义和设置。
  • SchedulerFactory负责初始化,读取配置文件,然后创建Scheduler
  • Scheduler是中枢调度器,负责管理Trigger/JobDetail和3个调度线程
    1. QuartzSchedulerThread 主调度线程


      调度任务主流程 (1).png
  1. MisfireHandler 错失触发的任务恢复线程,。更新Trigger的触发时间。
  2. ClusterManager 集群协调线程。定期心跳,自动recover。同主程序中的recover。

SpringBoot2.0集成Quartz

从boot2.0开始,增加了对Quartz的自动装配,以前需要自己处理。
以集群配置为例,最基本的操作是这样的:

  • Maven依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
  • 编写具体的job
    public class TestJob extends QuartzJobBean {
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            System.out.println("Test job executed.");
        }
    }
  • 定义JobDetail, 把Job的class类型传入。Spring自动处理
    @Bean
    public JobDetail testJob(){
        return JobBuilder
                .newJob(TestJob.class)
                .withIdentity("TestJob")
                .storeDurably()
                .requestRecovery()
                .build();
    }
  • 定义Trigger, 通过Key关联JobDetail。Spring 自动处理。
    @Bean
    public Trigger testTrigger(){
        return TriggerBuilder.newTrigger()
            .withIdentity("TestTrigger")
            .forJob("TestJob")
            .withSchedule(CronScheduleBuilder
                    .cronSchedule("0/6 * * * * ? ")
                    .withMisfireHandlingInstructionDoNothing())
            .build();
    }
  • 如果需要不同的数据库,定义一个@Primary主库,和一个@QuartzDataSource quartz专用库
    @Bean
    @Primary
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @QuartzDataSource
    @ConfigurationProperties(prefix="spring.datasource.quartz")
    public DataSource quartzDataSource() {
        return DataSourceBuilder.create().build();
    }
  • application.properties 都有默认配置,第一行启用数据库,后面两行是cluster功能
spring.quartz.job-store-type=jdbc
spring.quartz.org.quartz.scheduler.instanceId = AUTO
spring.quartz.org.quartz.jobStore.isClustered = true
  • 虽然Spring提供了自动建库的功能,但是第一次建完之后需要改成never
spring.quartz.jdbc.initializeSchema=ALWAYS
#spring.quartz.jdbc.initializeSchema=NEVER
  • 手动建库可以从官网下载的全家桶,或者Jar包中获得

    1. 全家桶:{dir}/docs/dbTables/tables_{database}.sql
    2. Jar:classpath:/org/quartz/impl/jdbcjobstore/tables_{database}.sql
  • 想看源码的可以从org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration进

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 概述 了解Quartz体系结构 Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器、任务和触发器这3个...
    张晨辉Allen阅读 6,628评论 2 11
  • 什么是定时任务调度 基于给定的时间点,给定的时间间隔或者给定的执行次数自动完成执行任务 在Java中的定时调度工具...
    Hey_Shaw阅读 7,311评论 2 1
  • Quartz原理解密 Author: DoraeDate:2018年7月17日15:55:02转载请注明出处 由于...
    Dorae132阅读 5,399评论 0 3
  • 本文是根据 Quartz定时器官方文档翻译的,只翻译了第1到第10课,如有翻译不精确的地方,请读者指正,互相学习,...
    ChinaXieShuai阅读 12,715评论 1 19
  • 未来总是这般美好多少人却迟迟不前或迷茫!或彷徨终点是什么样子走啊,走啊多少后悔、错过占满路旁 越过万千山远去故乡是...
    琴霄阅读 3,038评论 2 2