调度介绍 - Quartz

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 众所周知,Quartz作为知名的企业级调度框架,提供了丰富的特性。本文通过一个简单的示例,介绍下quartz在springboot的应用和quartz部分基本概念,并展示了quartz调度作业的基本过程。

1.先看效果

image.png
通过上图打印日志信息,我们可以知道,作业会经历一个这样的生命周期:触发器触发 -> 作业即将被执行 -> 作业被执行 -> 作业执行完成 -> 本次调度触发完成。

2.看项目结构

image.png

3.看关键类

3.1 StartRunner

StartRunner实现了ApplicationRunner,会随着Springboot启动被执行。该类主要作用是启动Quartz并读取配置文件中作业相关配置信息,将作业加入调度计划。

  • 配置项:
system.job.classNameList=com.example.little.job.BusinessJob
system.job.cronList=0/30 ?
  • StartRunner,注入了QzService
public class StartRunner implements ApplicationRunner {

    @Autowired
    private QzService qzService;

    @Autowired
    private JobInfoConfig jobInfoConfig;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        qzService.start();
        log.info("我的日志: qz调度启动.");
        String[] jobList = jobInfoConfig.getClassNameList();
        String[] cronList = jobInfoConfig.getCronList();
        for (int i = 0; i < jobList.length; i++) {
            JobInfo jobInfo = new JobInfo();
            jobInfo.setClassName(jobList[i].trim());
            jobInfo.setCron(cronList[i].trim());
            qzService.addJob(jobInfo);
        }
    }
}

3.2 QzService

具体实现类是QuartzServiceImpl,封装了Quartz的调度器Scheduler常用功能。示例中的调度启动start()方法,在启动时加入了各种类型的Listener;作业加入调度的addJob(),可将作业加入调度。当然Quartz还支持作业暂定、移除、恢复调度等很多的功能。此处仅做演示,代码如下:

@Service
public class QzServiceImpl implements QzService {

    @Autowired
    Scheduler scheduler;

    @Override
    public void start() throws Exception {
        scheduler.getListenerManager().addJobListener(new JobListener());
        scheduler.getListenerManager().addTriggerListener(new TriggerListener());
        scheduler.getListenerManager().addSchedulerListener(new SchedulerListener());
        scheduler.start();
    }

    @Override
    public void addJob(JobInfo jobInfo) throws Exception {
        Class clazz_ = Class.forName(jobInfo.getClassName());
        JobDetail jobDetail = JobBuilder.newJob(clazz_).build();
        Trigger trigger = TriggerBuilder.newTrigger().
                withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCron())).build();
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

3.3 SchedulerListener

见名知意,是调度相关事件的监听器,这里仅实现了两个方法,作业加入调度时会通知jobAdd()方法,scheduler将job和trigger绑定的时候会通知jobScheduled()方法。代码如下:

@Slf4j
public class SchedulerListener extends SchedulerListenerSupport {

    @Override
    public void jobAdded(JobDetail jobDetail) {
        super.jobAdded(jobDetail);
        log.info("我的日志: job被加入调度 ,key {}", jobDetail.getKey());
    }

    @Override
    public void jobScheduled(Trigger trigger) {
        super.jobScheduled(trigger);
        log.info("我的日志:作业开始被调度 ,key {}", trigger.getKey());
    }
}

3.4.TriggerListener

trigger事件监听器,当trigger到达执行时间被触发时,会通知triggerFired()方法;当触发完成后,会通知triggerComplete()方法;当trigger错过调度时间时,会通知triggerMisfired()方法。

public class TriggerListener extends TriggerListenerSupport {
    @Override
    public String getName() {
        return "little_trigger";
    }

    @Override
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        super.triggerFired(trigger, context);
        log.info("我的日志: trigger触发开始 {}", trigger.getKey());
    }

    @Override
    public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        super.triggerComplete(trigger, context, triggerInstructionCode);
        log.info("我的日志:trigger触发结束  {}  ", trigger.getKey());
    }

    @Override
    public void triggerMisfired(Trigger trigger) {
        super.triggerMisfired(trigger);
        log.info("我的日志,trigger错过触发 {} ", trigger.getKey());
    }
}

3.5 JobListener

job的事件监听器,作业将要被执行时,会通知jobToBeExecuted()方法;作业执行完成时,会通知jobWasExecuted()方法。想一下,这里是不是可以在作业执行的前后做些什么?比如日志、执行情况记录等等。

public class JobListener extends JobListenerSupport {
    @Override
    public String getName() {
        return "little_job";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        super.jobToBeExecuted(context);
        log.info("我的日志: job将要被执行");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        super.jobWasExecuted(context, jobException);
        log.info("我的日志:job执行完成");
    }
}

相关概念

  • Scheduler:Quartz的核心调度器,提供了调度器启动、终止、作业新增、暂定、移除、恢复调度等丰富的功能。
  • Job(QuartzJobBean):QuartzJobBean是Spring对quartz的Job的包装,只有一个方法,用于实现真正要被调度的业务逻辑。
  • Trigger:触发器,时间到达执行时间时会被触发,去触发Job的执行。
  • 各类监听器:标准的观察者模式,可根据业务需要进行扩展,对于作业的全生命周期进行监控或者控制,比如本示例的日志打印。作业监听器JobListenerSupport,调度监听器SchedulerListenerSupport,触发器监听TriggerListenerSupport。

其他

1.示例中,通过配置文件+ApplicationRunner的方式来将作业加入quartz执行,可改为读取数据库方式,实现更加灵活的作业管控。
2.示例中,各类监听器,监听到事件时仅仅做了日志打印动作,实际可根据业务需要进行一些记录或者作业执行过程中的管控。

参考

1.官网,quartz官方文档。
2.示例,一个简单的示例,介绍了许多常用的API。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
存储 监控 算法
Xxljob调度机制
时间轮算法,其实很简单,就是用实际的时钟刻度槽位来存储任务。 时钟刻度可以更细致,比如把一天切分成246060个秒的刻度,秒的刻度上挂任务。
815 0
Xxljob调度机制
|
存储 运维 Java
分布式定时任务-Quartz
分布式定时任务-Quartz
分布式定时任务-Quartz
|
存储 Java 数据库连接
Quartz:任务调度实现原理
Quartz:任务调度实现原理
1317 0
Quartz:任务调度实现原理
|
Java 调度 Spring
调度介绍 - Quartz是怎么调起来的
Quartz调度核心类QuartzSchedulerThread,是一个线程。在线程启动后,通过while循环不断去触发作业的执行。ps:源码版本2.3.2,
调度介绍 - Quartz是怎么调起来的
|
监控 关系型数据库 调度
Spring整合Quartz分布式调度
为了保证应用的高可用和高并发性,一般都会部署多个节点;对于定时任务,如果每个节点都执行自己的定时任务,一方面耗费了系统资源,另一方面有些任务多次执行,可能引发应用逻辑问题,所以需要一个分布式的调度系统,来协调每个节点执行定时任务。
8549 0
|
Java Apache 调度
利用quartz实现定时调度
1、Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。这里我介绍quartz的两种方式。我这里搭建的框架是采用springboot、spring-data-jpa、mysql、quartz的方式来实现。
1203 0
|
前端开发 Java 调度
Quartz 定时器任务调度
Job:是一个接口只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在 JobDataMap实例中 第一种,作业类继承自特定的基  1.8测试成功,2.0不行类:org.springframework.scheduling.
1892 0