Quartz的分布式任务调度应用

目录

 

Quartz 基本概念及原理

Quartz Scheduler 开源框架

Quartz 任务调度的基本实现原理

线程视图

基本的开发流程及简单实例

quartz企业级开发中的常见应用的一些问题及常见的解决方案


Quartz 基本概念及原理

Quartz Scheduler 开源框架

Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。读者可以到 http://www.quartz-scheduler.org/站点下载 Quartz 的发布版本及其源代码。笔者在产品开发中使用的是版本 1.8.4,因此本文内容基于该版本。本文不仅介绍如何应用 Quartz 进行开发,也对其内部实现原理作一定讲解。

作为一个优秀的开源调度框架,Quartz 具有以下特点:

  1. 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
  2. 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
  3. 分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。本文暂不讨论该部分内容

另外,作为 Spring 默认的调度框架,Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

下面是本文中用到的一些专用词汇,在此声明:

scheduler:

任务调度器

trigger:

触发器,用于定义任务调度时间规则

job:

任务,即被调度的任务

misfire:

错过的,指本来应该被执行但实际没有被执行的任务调度

 

Quartz 任务调度的基本实现原理

核心元素

Quartz 任务调度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任务调度的元数据, scheduler 是实际执行调度的控制器。

在 Quartz 中,trigger 是用于定义调度时间的元素,即按照什么时间规则去执行任务。Quartz 中主要提供了四种类型的 trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger。这四种 trigger 可以满足企业应用中的绝大部分需求。我们将在企业应用一节中进一步讨论四种 trigger 的功能。

在 Quartz 中,job 用于表示被调度的任务。主要有两种类型的 job:无状态的(stateless)和有状态的(stateful)。对于同一个 trigger 来说,有状态的 job 不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。Job 主要有两种属性:volatility 和 durability,其中 volatility 表示任务是否被持久化到数据库存储,而 durability 表示在没有 trigger 关联的时候任务是否被保留。两者都是在值为 true 的时候任务被持久化或保留。一个 job 可以被多个 trigger 关联,但是一个 trigger 只能关联一个 job。

在 Quartz 中, scheduler 由 scheduler 工厂创建:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二种工厂 StdSchedulerFactory 使用较多,因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。 Scheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。本文以最常用的 StdScheduler 为例讲解。这也是笔者在项目中所使用的 scheduler 类。

Quartz 核心元素之间的关系如下图所示:

线程视图

Scheduler 调度线程主要有两个: 执行常规调度的线程,和执行 misfired trigger 的线程。常规调度线程轮询存储的所有 trigger,如果有需要触发的 trigger,即到达了下一次触发的时间,则从任务执行线程池获取一个空闲线程,执行与该 trigger 关联的任务。Misfire 线程是扫描所有的 trigger,查看是否有 misfired trigger,如果有的话根据 misfire 的策略分别处理。下图描述了这两个线程的基本流程:

 

基本的开发流程及简单实例

下载相应的开发包

http://www.quartz-scheduler.org/downloads/

简单实例

  • 准备数据库和Quartz用的数据表

   新建数据库,并通过建表语句生成

建表语句建表结构

 

  • 定义任务实现类
实现无状态的Job接口
public class SampleStoreJob implements Job{
    private Logger logger = Logger.getLogger(SampleStoreJob.class);


    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //job任务实现类参数传递
        JobDetail detail = jobExecutionContext.getJobDetail();
        Integer taskId = detail.getJobDataMap().getIntValue("taskId");
        logger.info("SampleStoreJob===========execute()");
   
    }
}
  • 实现主程序
通过cron实现每隔两秒钟执行一次的任务调度
public class SampleStoreQuartz {
    public void run() throws Exception{
        //使用SchedulerFactory创建一个Scheduler
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.clear(); //测试用,避免因为调度存在报错,可以在job未delete的情况下删掉看下效果

        //定义一个具体的Job
        JobDetail jobDetail = JobBuilder.newJob(SampleStoreJob.class)
                .withIdentity("sampleStoreJob", "sampleJobGroup")
                .build();
        //定义一个具体的Trigger
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");//具体的执行时间定义
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("sampleStoreTrigger1", "sampleTriggerGroup1").withSchedule(scheduleBuilder).build();
        //将Job和Trigger绑定至Scheduler
        scheduler.scheduleJob(jobDetail, trigger);
        scheduler.start();//启动运行

        Thread.sleep(10*1000);//情节需要,10秒钟
        //定义一个JobKey,用来做删除Job测试
     //   JobKey jobKey = JobKey.jobKey("sampleStoreJob", "sampleJobGroup");
       // scheduler.deleteJob(jobKey);

      //  scheduler.shutdown();//关闭Scheduler
    }

    public static void main(String[] args) throws Exception{
        SampleStoreQuartz sampleStoreQuartz = new SampleStoreQuartz();
        sampleStoreQuartz.run();
    }

 

  • 核心代码
暂停任务Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.pauseJob(jobKey);
恢复任务Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.resumeJob(jobKey);
删除任务Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.deleteJob(jobKey);
立即运行任务Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); scheduler.triggerJob(jobKey);

 

  • 运行程序,查看数据库和运行结果
表名表记录
qrtz_triggers
qrtz_job_details

 

 

quartz企业级开发中的常见应用的一些问题及常见的解决方案

 

使用有状态的StatefulJob还是无状态的Job在quartz中,Job是一个接口,企业应用需要实现这个接口,以定义自己的任务,基本来说,任务分为有状态和无状态两种,实现Job接口的任务缺省为无状态的,Quartz中海油一个应用接口StatefulJob,是有状态的,有状态的, 当任务未执行完,是不能并发执行的,比如若有些任务不能并发执行,可以考虑有状态的接口,并配合misfiredjob
如何设置Quartz的线程池和并发任务Quartz自带了一个线程池的实现:SimpleThreadPool,并提供了默认的配置参数,不如线程数等,并不是线程数,越多越好,可以根据自己的业务灵活调整
如何处理Misfired任务

1)系统因为某些原因被重启。在系统关闭到重新启动之间的一段时间里,可能有些任务会

被 misfire;

2)Trigger 被暂停(suspend)的一段时间里,有些任务可能会被 misfire;

3)线程池中所有线程都被占用,导致任务无法被触发执行,造成 misfire;

4)有状态任务在下次触发时间到达时,上次执行还没有结束;

为了处理 misfired job,Quartz 中为 trigger 定义了处理策略,主要有下面两种:

MISFIRE_INSTRUCTION_FIRE_ONCE_NOW:针对 misfired job 马上执行一次;

MISFIRE_INSTRUCTION_DO_NOTHING:忽略 misfired job,等待下次触发;

建议读者在应用开发中,将该设置作为可配置选项,使得用户可以在使用过程中,针对已经添加的 tirgger 动态配置该选项。

 

 

 

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。 Quartz的优势: 1、Quartz是一个任务调度框架(库),它几乎可以集成到任何应用系统中。 2、Quartz是非常灵活的,它让您能够以最“自然”的方式来编写您的项目的代码,实现您所期望的行为 3、Quartz是非常轻量级的,只需要非常少的配置 —— 它实际上可以被跳出框架来使用,如果你的需求是一些相对基本的简单的需求的话。 4、Quartz具有容错机制,并且可以在重启服务的时候持久化(”记忆”)你的定时任务,你的任务也不会丢失。 5、可以通过Quartz,封装成自己的分布式任务调度,实现强大的功能,成为自己的产品。6、有很多的互联网公司也都在使用Quartz。比如美团 Spring是一个很优秀的框架,它无缝的集成了Quartz,简单方便的让企业级应用更好的使用Quartz进行任务的调度。   课程说明:在我们的日常开发中,各种大型系统的开发少不了任务调度,简单的单机任务调度已经满足不了我们的系统需求,复杂的任务会让程序猿头疼, 所以急需一套专门的框架帮助我们去管理定时任务,并且可以在多台机器去执行我们的任务,还要可以管理我们的分布式定时任务。本课程从Quartz框架讲起,由浅到深,从使用到结构分析,再到源码分析,深入解析Quartz、Spring+Quartz,并且会讲解相关原理, 让大家充分的理解这个框架和框架的设计思想。由于互联网的复杂性,为了满足我们特定的需求,需要对Spring+Quartz进行二次开发,整个二次开发过程都会进行讲解。Spring被用在了越来越多的项目中, Quartz也被公认为是比较好用的定时器设置工具,学完这个课程后,不仅仅可以熟练掌握分布式定时任务,还可以深入理解大型框架的设计思想。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值