Углубленная интерпретация планировщика задач Quartz
1. Введение в кварц
1.1. Обзор
Quartz — это мощная платформа планирования задач с открытым исходным кодом, предоставляемая OpenSymphony.
Официальный сайт:www.quartz-scheduler.org
Чистая реализация Java, точное планирование управления.
1.2. Особенности кварца
- Мощные возможности планирования
- гибкое приложение
- Мощные возможности распределения и кластеризации
1.3.Кварцевые шаблоны проектирования
- Режим строителя
- шаблон компонента
- Заводской режим
- Цепное письмо
1.4.Кварцевая архитектура
1.4.1 Три ядра
- планировщик
- Задача
- курок
1.4.2. Важные компоненты
1) Задача:
-
Задание: указывает задание, конкретное содержимое, которое необходимо выполнить. В этом интерфейсе есть только один метод. Для создания задачи необходимо реализовать этот интерфейс. Этот интерфейс имеет только один метод выполнения, и логика метода выполнения выполняется каждый раз при вызове задачи, аналогично методу запуска TimerTask, в котором написана бизнес-логика.
public class TestJob implements Job { /**把要执行的操作,写在execute方法中 */ @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); System.out.println("I can do something..."); System.out.println(sdf.format(new Date())); } }
Жизненный цикл: каждый раз, когда планировщик выполняет задание, он создает новый экземпляр задания перед вызовом метода выполнения.По завершении вызова соответствующий экземпляр объекта задания будет освобожден, а освобожденный экземпляр будет переработан сборщиком мусора. механизм.
-
JobBuilder: он может передавать данные в задачу. Обычно мы можем использовать его для отправки данных в класс задачи. Если есть особенно сложные параметры для передачи, он предоставляет метод для передачи объекта JobDataMap.
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("testJob","group1").build();
-
JobDetail: используется для сохранения сведений о нашей работе. JobDetail может иметь несколько Trigger, но Trigger может соответствовать только одному JobDetail. Ниже приведены некоторые часто используемые свойства и значения JobDetail:
-
JobStore: Отвечает за отслеживание всех «данных задания», которые вы предоставляете планировщику: задания, триггеры, календари и т. д.
-
RAMJobStore: самый простой и эффективный (с точки зрения процессорного времени) магазин заданий. RAMJobStore Как следует из названия, он хранит данные в оперативной памяти. Недостатком является то, что все данные теряются после завершения работы вашего приложения — это означает, что RAMJobStore не может сохранять задания и триггеры постоянными. Это допустимо и даже желательно для одних программ, но может иметь катастрофические последствия для других. Настройте Quartz с помощью RAMJobStore: конфигурация выглядит следующим образом.
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
-
JDBCJobStore: сохраняет данные в базе данных способом JDBC. Он немного сложнее в настройке, чем RAMJobStore, и не так быстр, как RAMJobStore. Однако недостаток производительности не страшен, особенно если у вас есть индексы по первичному ключу таблицы базы данных. При разумной локальной сети между машинами (между планировщиком и базой данных) получение и обновление сработавшего триггера занимает менее 10 мс. Применяется практически ко всем базам данных, широко используемым в Oracle. PostgreSQL, MySQL, MS SQLServer, HSQLDB и DB2. Прежде чем использовать JDBCJobStore, вы должны сначала создать набор таблиц, которые будет использовать Quartz. Инструкции по созданию таблиц можно найти в каталоге дистрибутива Quartz в разделе «docs/dbTables». Вам необходимо определить тип транзакции, которую будет использовать ваше приложение. Если вы не хотите привязывать команды планирования (такие как добавление и удаление триггеров) к другим транзакциям, вы можете использовать JobStoreTX (наиболее распространенный вариант) в качестве своего магазина заданий. Если вам нужно, чтобы Quartz работал с другими транзакциями (например, на сервере приложений J2EE), вам следует использовать JobStoreCMT, Quartz позволит контейнеру сервера приложений управлять транзакциями. Настройте Quartz с помощью JobStoreTx:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate #配置表的前缀 org.quartz.jobStore.tablePrefix = QRTZ_ #使用JNDI数据源的时候,数据源的名字 org.quartz.jobStore.dataSource = myDS
-
TerracottaJobStore: позволяет сделать его сжимаемым и надежным без использования базы данных. Может быть кластеризованным или некластеризованным, в обоих случаях обеспечивает механизм хранения данных вашего задания, чтобы они сохранялись между перезапусками приложения, поскольку данные хранятся на сервере Terracotta. Он работает немного лучше (примерно на порядок), чем использование базы данных для доступа к JDBCJobStore, но значительно медленнее, чем RAMJobStore. Настройте Quartz с помощью TerracottaJobStore:
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore org.quartz.jobStore.tcConfigUrl = localhost:9510
-
-
JobDataMap: может содержать неограниченное количество (сериализованных) объектов данных, и данные могут использоваться при выполнении экземпляра задания; JobDataMap — это реализация интерфейса Java Map с некоторыми дополнительными функциями, облегчающими доступ к базовым типам данных. , метод.
-
реальный:
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("testJob","group1").usingJobData("date1","存内容").build();
-
Выбирать:
public class TestJob implements Job { /**把要执行的操作,写在execute方法中 */ @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { JobKey key = jobExecutionContext.getJobDetail().getKey(); JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); String date1 = jobDataMap.getString("date1"); } }
-
2) Триггер: используется для запуска выполнения задания.
2.1) Общие свойства триггера:
- Ключ задания: указывает идентификатор экземпляра задания.При срабатывании триггера указанный экземпляр задания будет выполнен.
- StartTime: указывает время, когда расписание триггера срабатывает в первый раз, и его тип значения: java.util.Date
- EndTime: указывает время, когда триггер больше не срабатывает.Его тип значения: java.util.Date.
2.2) Тип триггера:
-
SimpleTrigger: в основном используется для настройки и использования некоторых относительно простых временных триггеров, таких как запуск в указанное время, а затем повторение задания в течение определенного интервала времени, а количество повторений может быть указано произвольно. Вот пример использования SimpleTrigger:
//创建触发器 每3秒钟执行一次(无开始时间和结束时间) Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group3") .withSchedule( SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(3).repeatForever()).build(); //创建触发器 每3秒钟执行一次(有开始时间和结束时间) long now = new Date().getTime(); Date start = new Date(now+6000); Date end = new Date(now+12000); //创建触发器 每3秒钟执行一次 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group3") .startAt(start) .endAt(end) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever()).build();
SimpleTrigger имеет богатые конструкторы, и различные конструкторы создаются в соответствии с бизнес-требованиями.
-
CronTrigger: можно настроить более сложные расписания триггеров, триггеры заданий на основе календаря вместо точного указания интервалов, как SimpleTrigger, используются чаще, чем SimpleTrigger.
Выражение Cron: используется для настройки экземпляра CronTrigger, представляет собой строку, состоящую из 7 выражений, описывающих детали расписания.
Формат: [секунды][минуты][часы][дни][месяцы][недели][годы].
Специальный символ выражения Cron, означающий таблицу соответствий:
Описание подстановочного знака:
Пример выражения cron:
TriggerBuilder.newTrigger().withIdentity("trigger2","group2")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 9 ? * 6L *")).build();
Советы по выражению Cron:
1. «L» и «W» можно использовать вместе
2. Английские буквы поля недели нечувствительны к регистру, то есть MOM — это то же самое, что и mom
3. Используйте инструменты для генерации выражений cron онлайн:cron.qqe2.com/
-
NthIncludedDayTrigger: последний триггер, добавленный в платформу командой разработчиков Quartz. Он предназначен для выполнения задания в день каждого типа интервала. Например, если вы хотите выполнять задание по выставлению счетов 15-го числа каждого месяца, идеально подойдет NthIncludedDayTrigger.
NthIncludedDayTrigger trigger = new NthIncludedDayTrigger("NthIncludedDayTrigger",Scheduler.DEFAULT_GROUP); trigger.setN(15); trigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_MONTHLY);
3) Планировщик Планировщик
Представляет собой независимый запущенный контейнер Quartz. Trigger и JobDetail могут быть зарегистрированы в Scheduler. Оба имеют собственную группу и имя в Scheduler. Группа и имя являются основанием для Scheduler для поиска объекта в контейнере. Группа и имя Trigger должны быть быть уникальным, группа и имя JobDetail также должны быть уникальными (но могут совпадать с группой и именем триггера, поскольку они относятся к разным типам). Scheduler определяет ряд методов интерфейса, обеспечивающих внешний доступ и управление Trigger и JobDetail в контейнере по группе и имени.
Планировщик может привязать триггер к JobDetail, чтобы при срабатывании триггера выполнялось соответствующее задание. Задание может соответствовать нескольким триггерам, но триггер может соответствовать только одному заданию.
Экземпляр Scheduler можно создать с помощью SchedulerFactory. Планировщик имеет SchedulerContext, который похож на ServletContext и содержит контекстную информацию планировщика.И Job, и Trigger могут получить доступ к информации в SchedulerContext. SchedulerContext поддерживает эти данные контекста в виде пар ключ-значение через внутреннюю карту. SchedulerContext предоставляет несколько методов put() и getXxx() для сохранения и получения данных. Вы можете получить соответствующий экземпляр SchedulerContext через Scheduler# getContext();
SchedulerFactory schedulerfactory=new StdSchedulerFactory();
Scheduler scheduler = schedulerfactory.getScheduler();
DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance();
try {
Scheduler scheduler = factory.getScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
}
4)SchedulerFactory:
- Используйте набор параметров (java.util.Properties) для создания и публикации планировщика Quartz.
- Параметры конфигурации обычно хранятся в файлеquart.properties.
- Вызовите метод getScheduler для создания и инициализации планировщика.
5)quartz.properties:
Конфигурационный файл Quartz-Job Quartz.properties показывает, что этот файл находится в пакете кварцевой банки и может использоваться напрямую, но только несколько базовых конфигураций могут быть расширены по мере необходимости, кроме того, если файл конфигурации не переписывается в проекте, Quartz загрузит файлquartz.properties в свой собственный пакет jar.
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#org.quartz.scheduler.instanceid:AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
# ===========================================================================
# Configure ThreadPool 线程池属性
# ===========================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount: 10
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority: 5
#设置SimpleThreadPool的一些属性
#设置是否为守护线程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#线程前缀默认值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;
# 配置全局监听(TriggerListener,JobListener) 则应用程序可以接收和执行 预定的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger监听器
# MyTriggerListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job监听器
# MyJobListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configure JobStore 存储调度信息(工作,触发器和日历等)
# ===========================================================================
# 信息保存时间 默认值60秒
org.quartz.jobStore.misfireThreshold: 60000
#保存job和Trigger的状态信息到内存中的类
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
# ===========================================================================
# Configure SchedulerPlugins 插件属性 配置
# ===========================================================================
# 自定义插件
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger执行历史日志(可以看到类的文档和参数列表)
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy} with resulting trigger instruction code: {9}
#配置job调度插件 quartz_jobs(jobs and triggers内容)的XML文档
#加载 Job 和 Trigger 信息的类 (1.8之前用:org.quartz.plugins.xml.JobInitializationPlugin)
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
#指定存放调度器(Job 和 Trigger)信息的xml文件,默认是classpath下quartz_jobs.xml
org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
#自动扫描任务单并发现改动的时间间隔,单位为秒
org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
# ===========================================================================
# Sample configuration of ShutdownHookPlugin ShutdownHookPlugin插件的配置样例
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#
# Configure RMI Settings 远程服务调用配置
#
#如果你想quartz-scheduler出口本身通过RMI作为服务器,然后设置“出口”标志true(默认值为false)。
#org.quartz.scheduler.rmi.export = false
#主机上rmi注册表(默认值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#注册监听端口号(默认值1099)
#org.quartz.scheduler.rmi.registryport = 1099
#创建rmi注册,false/never:如果你已经有一个在运行或不想进行创建注册
# true/as_needed:第一次尝试使用现有的注册,然后再回来进行创建
# always:先进行创建一个注册,然后再使用回来使用注册
#org.quartz.scheduler.rmi.createregistry = never
#Quartz Scheduler服务端端口,默认是随机分配RMI注册表
#org.quartz.scheduler.rmi.serverport = 1098
#true:链接远程服务调度(客户端),这个也要指定registryhost和registryport,默认为false
# 如果export和proxy同时指定为true,则export的设置将被忽略
#org.quartz.scheduler.rmi.proxy = false