Scheduler
好比一个容器,可以装入JobDetail和Trigger,可以设定Trigger触发JobDetail
SchedulerFactory
Property Name | Type | Default Value |
---|---|---|
org.quartz.scheduler.instanceName | string | ‘QuartzScheduler’ |
org.quartz.scheduler.instanceId | string | ‘NON_CLUSTERED’ |
org.quartz.scheduler.instanceIdGenerator.class | string (class name) | org.quartz.simpl.SimpleInstanceIdGenerator |
org.quartz.scheduler.threadName | string | instanceName + ‘_QuartzSchedulerThread’ |
org.quartz.scheduler.makeSchedulerThreadDaemon | boolean | false |
org.quartz.scheduler .threadsInheritContextClassLoaderOfInitializer | boolean | false |
org.quartz.scheduler.idleWaitTime | long | 30000 |
org.quartz.scheduler.dbFailureRetryInterval | long | 15000 |
org.quartz.scheduler.classLoadHelper.class | string (class name) | org.quartz.simpl.CascadingClassLoadHelper |
org.quartz.scheduler.jobFactory.class | string (class name) | org.quartz.simpl.PropertySettingJobFactory |
org.quartz.context.key.SOME_KEY | string | none |
org.quartz.scheduler.userTransactionURL | string (url) | ‘java:comp/UserTransaction’ |
org.quartz.scheduler.wrapJobExecutionInUserTransaction | boolean | false |
org.quartz.scheduler.skipUpdateCheck | boolean | false |
org.quartz.scheduler.batchTriggerAcquisitionMaxCount | int | 1 |
org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow | long | 0 |
org.quartz.scheduler.instanceName
Can be any string, and the value has no meaning to the scheduler itself - but rather serves as a mechanism for clientcode to distinguish schedulers when multiple instances are used within the same program. If you are using the clusteringfeatures, you must use the same name for every instance in the cluster that is ‘logically’ the same Scheduler.
org.quartz.scheduler.instanceId
Can be any string, but must be unique for all schedulers working as if they are the same ‘logical’ Scheduler within acluster. You may use the value “AUTO” as the instanceId if you wish the Id to be generated for you. Or the value“SYS_PROP” if you want the value to come from the system property “org.quartz.scheduler.instanceId”.
org.quartz.scheduler.instanceIdGenerator.class
Only used if org.quartz.scheduler.instanceId is set to “AUTO”. Defaults to“org.quartz.simpl.SimpleInstanceIdGenerator”, which generates an instance id based upon host name and time stamp.Other IntanceIdGenerator implementations include SystemPropertyInstanceIdGenerator (which gets the instance idfrom the system property “org.quartz.scheduler.instanceId”, and HostnameInstanceIdGenerator which uses thelocal host name (InetAddress.getLocalHost().getHostName()). You can also implement the InstanceIdGeneratorinterface your self.
org.quartz.scheduler.threadName
Can be any String that is a valid name for a java thread. If this property is not specified, the thread will receive thescheduler’s name (“org.quartz.scheduler.instanceName”) plus an the appended string ‘_QuartzSchedulerThread’.
org.quartz.scheduler.makeSchedulerThreadDaemon
A boolean value (‘true’ or ‘false’) that specifies whether the main thread of the scheduler should be a daemon thread ornot. See also the org.quartz.scheduler.makeSchedulerThreadDaemon property for tuning the SimpleThreadPool if that is the thread pool implementationyou are using (which is most likely the case).
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer
A boolean value (‘true’ or ‘false’) that specifies whether the threads spawned by Quartz will inherit the contextClassLoader of the initializing thread (thread that initializes the Quartz instance). This will affect Quartz mainscheduling thread, JDBCJobStore’s misfire handling thread (if JDBCJobStore is used), cluster recovery thread (ifclustering is used), and threads in SimpleThreadPool (if SimpleThreadPool is used). Setting this value to ‘true’ mayhelp with class loading, JNDI look-ups, and other issues related to using Quartz within an application server.
org.quartz.scheduler.idleWaitTime
Is the amount of time in milliseconds that the scheduler will wait before re-queries for available triggers when thescheduler is otherwise idle. Normally you should not have to ‘tune’ this parameter, unless you’re using XA transactions,and are having problems with delayed firings of triggers that should fire immediately. Values less than 5000 ms are notrecommended as it will cause excessive database querying. Values less than 1000 are not legal.
org.quartz.scheduler.dbFailureRetryInterval
Is the amount of time in milliseconds that the scheduler will wait between re-tries when it has detected a loss ofconnectivity within the JobStore (e.g. to the database). This parameter is obviously not very meaningful when usingRamJobStore.
org.quartz.scheduler.classLoadHelper.class
Defaults to the most robust approach, which is to use the “org.quartz.simpl.CascadingClassLoadHelper” class - which inturn uses every other ClassLoadHelper class until one works. You should probably not find the need to specify any otherclass for this property, though strange things seem to happen within application servers. All of the current possibleClassLoadHelper implementation can be found in the org.quartz.simpl package.
org.quartz.scheduler.jobFactory.class
The class name of the JobFactory to use. A JobFatcory is responsible for producing instances of JobClasses.The default is ‘org.quartz.simpl.PropertySettingJobFactory’, which simply calls newInstance() on the class to producea new instance each time execution is about to occur. PropertySettingJobFactory also reflectivelysets the job’s bean properties using the contents of the SchedulerContext and Job and Trigger JobDataMaps.
org.quartz.context.key.SOME_KEY
Represent a name-value pair that will be placed into the “scheduler context” as strings. (see Scheduler.getContext()).So for example, the setting “org.quartz.context.key.MyKey = MyValue” would perform the equivalent ofscheduler.getContext().put(“MyKey”, “MyValue”).
The Transaction-Related properties should be left out of the config file unless you are using JTA transactions.
org.quartz.scheduler.userTransactionURL
Should be set to the JNDI URL at which Quartz can locate the Application Server’s UserTransaction manager. The defaultvalue (if not specified) is “java:comp/UserTransaction” - which works for almost all Application Servers. Websphereusers may need to set this property to “jta/usertransaction”. This is only used if Quartz is configured to useJobStoreCMT, and org.quartz.scheduler.wrapJobExecutionInUserTransaction is set to true.
org.quartz.scheduler.wrapJobExecutionInUserTransaction
Should be set to “true” if you want Quartz to start a UserTransaction before calling execute on your job. The Tx willcommit after the job’s execute method completes, and after the JobDataMap is updated (if it is a StatefulJob). Thedefault value is “false”. You may also be interested in using the @ExecuteInJTATransaction annotationon your job class, which lets you control for an individual job whether Quartz should start a JTA transaction -whereas this property causes it to occur for all jobs.
org.quartz.scheduler.skipUpdateCheck
Whether or not to skip running a quick web request to determine if there is an updated version of Quartz available fordownload. If the check runs, and an update is found, it will be reported as available in Quartz’s logs. Youcan also disable the update check with the system property “org.terracotta.quartz.skipUpdateCheck=true” (whichyou can set in your system environment or as a -D on the java command line). It is recommended that you disablethe update check for production deployments.
org.quartz.scheduler.batchTriggerAcquisitionMaxCount
The maximum number of triggers that a scheduler node is allowed to acquire (for firing) at once. Default valueis 1. The larger the number, the more efficient firing is (in situations where there are very many triggers needing tobe fired all at once) - but at the cost of possible imbalanced load between cluster nodes. If the value of thisproperty is set to > 1, and JDBC JobStore is used, then the property “org.quartz.jobStore.acquireTriggersWithinLock”must be set to “true” to avoid data corruption.
org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow
The amount of time in milliseconds that a trigger is allowed to be acquired and fired ahead of its scheduled fire time. Defaults to 0. The larger the number, the more likely batch acquisition of triggers to fire will be able to select and fire more than 1 trigger at a time - at the cost of trigger schedule not being honored precisely (triggers may fire this amount early). This may be useful (for performance’s sake) in situations where the scheduler has very large numbers of triggers that need to be fired at or near the same time.
unschedule
1 |
|
Job
具体任务接口
JobExecutionContext
DisallowConcurrentExecution
不允许Job并发执行的注解,默认情况下Job是允许并发执行的
PersistJobDataAfterExecution
持久化JobData的注解
JobDetail
对Job的包装,同一个JobDetail可以被多个Trigger关联。
JobKey:由name
和group
确定JobDetail的唯一性,group默认值DEFAULT
,否则报错如下:
1 |
|
JobBuilder:
JobClass:
JobDataMap:存储Job参数等信息
isDurable:当没有trigger关联时,是否持久化,比如unschedule后,trigger不存在了,JobDetail还在schedule中。
requestsRecovery:
Trigger
startTime:起始时间,默认当前时间,会自动运行一次
endTime:截止时间,
TriggerKey:由name
和group
确定Trigger的唯一性,group默认值DEFAULT
,否则报错如下:
1 |
|
Trigger可以直接设定JobDetail
JobDataMap:存储Job参数等信息,优先级高于JobDetail中的JobDataMap,实际执行时传递给Job的是merge后的JobDataMap
forJob:设定关联的JobDetail,优先级高于schedule指定的JobDetail
TriggerBuilder
用于构建Trigger
ScheduleBuilder
SimpleScheduleBuilder
1 |
|
CronScheduleBuilder
1 |
|
DailyTimeIntervalScheduleBuilder
基于周几的间隔调度
1 |
|
CalendarIntervalScheduleBuilder
基于日历的间隔调度(日历是不均匀的,每月天数不同,每隔5个月cron做不到(5不能被12整除))
1 |
|
DateBuilder
SimpleTrigger
CronTrigger
DailyTimeIntervalTrigger
CalendarIntervalTrigger
JobStore
store scheduling information (job, triggers and calendars)
sql脚本
数据库相关脚步在quartz-2.3.0.jar/org/quartz/impl/jdbcjobstore/
目录下,比如:tables_mysql_innodb.sql
。
共计11张表。
1 |
|
1 |
|
JobStoreTX
非JTA
JobStoreCMT
容器环境,使用JTA,需要两个数据源,一个容器管理,一个自用
Delegates
1 |
|
Datasources
ConnectionProvider
自带支持c3p0、HikariCP、JNDI和weblogic
ThreadPool
Listener
ListenerManager
Matcher
SchedulerListener
TriggerListener
Configuring a Global TriggerListener
1 |
|
JobListener
Configuring a Global JobListener
1 |
|
Plugins
SchedulerPlugin
quartz.properties
2.3.0 default
1 |
|
Cluster
Quartz集群通过fail-over和负载均衡可以带来高可用和可扩展。
通过org.quartz.jobStore.isClustered=true
开启集群。
多个实例的org.quartz.scheduler.instanceId
属性值不能一样(也可以设置为AUTO
(自动分配)),其他都可以一样
必须选择持久化
的JobStore
(JobStoreTX
或JobStoreCMT
),共享同一个数据库(抢锁)。
org.quartz.jobStore.clusterCheckinInterval
负载均衡:所有节点随机并行调度执行job,当job较多时负载机制为线性随机,当job较少时负载机制优先跟之前相同的节点
fail-over:对于recovery job,当其在调度执行时所在节点宕机了,其他节点会检测到后会重新调度执行,对于非recovery job则不会重新执行
Quartz集群最适合长时间运行任务或cpu密集型job。对于大量短时间的job,考虑将任务分区到不同的scheduler
集群实例如果在不同的服务器,必须保持时钟同步(秒级)
样例
启动日志会标示是否集群(is not clustered或is clustered)。
1 |
|
节点一
1 |
|
节点二
1 |
|
1 |
|
原因:cluster中各机器之间的时间不同步。 应同步各机器时间,另设置cluster-checkin iterval。 The systems are syncronized via NTP。
MISFIRE
当一个持久的触发器因为调度器被关闭,或者线程池中没有可用的线程,或者因为DisallowConcurrentExecution且Job执行时间过长等而错过了激活时间时,即没有在预计的时间触发执行,就可能会发生激活失败(misfire)
1 |
|
misfire判定
实际执行时间与预定的执行时间相差>misfireThreshold,则判定为misfire
1 |
|
misfire instruction
发生misfire后如何应对处理呢?misfire instruction就是用来定义处理策略的。
Trigger
1 |
|
SimpleTrigger
updateAfterMisfire()
1 |
|
NOW:立即执行,同时重新开始按计划执行
NEXT:不立即执行,以当前时间为基准,重新开始按计划执行
WITH_REMAINING_COUNT:指超时期内错过的执行机会作废
WITH_EXISTING_COUNT:指超时期内错过的执行机会不作废
1 |
|
样例
MISFIRE_INSTRUCTION_FIRE_NOW
如果repeat count大于0,则MISFIRE_INSTRUCTION_FIRE_NOW等价于MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
1 |
|
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
1 |
|
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
1 |
|
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
1 |
|
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
1 |
|
CronTrigger
1 |
|
DailyTimeIntervalTrigger
1 |
|
CalendarIntervalTrigger
1 |
|
spring
SchedulerFactoryBean
创建和配置Quartz Scheduler,管理其生命周期作为Spring上下文的一部分,暴漏Quartz Scheduler为bean用做依赖注入。
允许注入JobDetails,Calendars和Triggers,自动启动和停止Quartz Scheduler,一般情况下不需要直接使用Quartz Scheduler。动态创建任务场景才需要直接使用Quartz Scheduler。
datasource
JobDetailFactoryBean
SimpleTriggerFactoryBean
CronTriggerFactoryBean
MethodInvokingJobDetailFactoryBean
JobDetail和Job的一种适配,将POJO适配为Job
1 |
|
AdaptableJobFactory
Job工厂的一种适配,可以支持Job和Runnable
DelegatingJob
Job的一种适配,将Runnable适配为Job
QuartzJobBean和SpringBeanJobFactory
Job的一种适配,将POJO适配为Job,同时将SchedulerContext和JobDataMap中的属性自动注入到POJO
LocalDataSourceJobStore
基于Spring管理的数据源的JobStoreCMT实现
LocalTaskExecutorThreadPool
基于Spring管理的Executor的ThreadPool实现
spring-boot-starter-quartz
QuartzAutoConfiguration
会自动注入JobDetail、Trigger、Calendar、QuartzProperties和SchedulerFactoryBeanCustomizer的实例bean。
使用Quartz原生数据源
1 |
|
使用自定义数据源(需要DataSource实现和spring-jdbc)
1 |
|
1 |
|
1 |
|