美文网首页程序员Java 杂谈
Quartz设计原理详解(多图)

Quartz设计原理详解(多图)

作者: 黄大海 | 来源:发表于2018-12-21 15:10 被阅读12次

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

    对于简单的任务处理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设计原理详解(多图)

        本文链接:https://www.haomeiwen.com/subject/kgsukqtx.html