您的位置:首页 > 其它

Quartz任务调度框架

2016-08-19 17:07 225 查看

Quartz 基本概念及原理

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

1、强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;

2、 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;

3、分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。本文暂不讨论该部分内容。

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

Quartz专用词汇:

scheduler :任务调度器

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

job :任务,即被调度的任务

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

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

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

trigger 是用于定义调度时间的元素,即按照什么时间规则去执行任务。

Quartz 中主要提供了四种类型的 trigger:

SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger。

job 用于表示被调度的任务

两种类型:无状态的(stateless)和有状态的(stateful)。对于同一个 trigger 来说,有状态的 job 不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。

Job 主要有两种属性:volatility 和 durability,其中 volatility 表示任务是否被持久化到数据库存储,而 durability 表示在没有 trigger 关联的时候任务是否被保留。两者都是在值为 true 的时候任务被持久化或保留。job : trigger -> 1 : n

scheduler 由 scheduler 工厂创建:DirectSchedulerFactory 或者 StdSchedulerFactory。StdSchedulerFactory使用广泛。

Scheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler

Quartz 核心元素关系图



在 Quartz 中,有两类线程,Scheduler调度线程和任务执行线程,其中任务执行线程通常使用一个线程池维护一组线程。

Quartz 线程视图



Scheduler 调度线程主要有两个: 执行常规调度的线程,和执行 misfired trigger 的线程。

Quartz 调度线程流程图



企业级开发中的常见应用

一、如何使用不同类型的 Trigger

SimpleTrigger

SimpleTrigger 一般用于实现每隔一定时间执行任务,以及重复多少次,如每 2 小时执行一次,重复执行 5 次。

SimpleTrigger 内部实现机制是通过计算间隔时间来计算下次的执行时间,这就导致其不适合调度定时的任务。

注意这里就会有一个问题,即当有 misfired 的任务并且恢复执行时,该执行时间是随机的(取决于何时执行 misfired 的任务,例如某天的 3:00PM)。这会导致之后每天的执行时间都会变成 3:00PM,而不是我们原来期望的 1:00AM。

CronTirgger

类似于 LINUX 上的任务调度命令 crontab,即利用一个包含 7 个字段的表达式来表示时间调度方式。对于涉及到星期和月份的调度,CronTirgger 是最适合的

Cron 表达式包括以下 7 个字段:

秒、分、小时、月内日期、月、周内日期、年(可选字段)

Cron 触发器利用一系列特殊字符:

反斜线(/)字符表示增量值

秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。

问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。

问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行

在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。

井号(#)字符为给定月份指定具体的工作日实例

星号(*)字符是通配字符,表示该字段可以接受任何可能的值。

DateIntervalTrigger

Quartz 1.7 之后的版本加入的,其最适合调度类似每 N(1, 2, 3…)小时,每 N 天,每 N 周等的任务。DateIntervalTrigger 不会受到我们上面说到的 misfired 任务的影响,也不会受到 DST(Daylight Saving Time, 即中国的夏令时)调整的影响。

NthIncludedDayTrigger

NthIncludedDayTrigger 的用途比较简单明确,即用于每隔一个周期的第几天调度任务,例如,每个月的第 3 天执行指定的任务。

二、使用有状态(StatefulJob)还是无状态的任务(Job)

在 Quartz 中,Job 是一个接口,企业应用需要实现这个接口以定义自己的任务。

任务分为有状态和无状态两种。

实现 Job 接口的任务缺省为无状态的。Quartz 中还有另外一个接口 StatefulJob

Quartz 中 Job 接口定义



无状态任务一般指可以并发的任务,即任务之间是独立的,不会互相干扰

三、如何设置 Quartz 的线程池和并发任务

Quartz 中自带了一个线程池的实现:SimpleThreadPool

配置参数:org.quartz.threadPool.threadCount : 设定线程池的线程数量

在应用中,如果有更好的线程池,则可以在配置文件中通过下面参数替换 SimpleThreadPool:org.quartz.threadPool.class = myapp.GreatThreadPool



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  任务调度 quartz 框架