1. 程式人生 > >SpringBoot整合Quartz定時任務框架

SpringBoot整合Quartz定時任務框架

在這裡插入圖片描述

1、quartz排程核心元素:

Scheduler:任務排程器,是實際執行任務排程的控制器。在spring中通過SchedulerFactoryBean封裝起來。 Trigger:描述觸發Job執行的時間觸發規則。主要有SimpleTrigger和CronTrigger這兩個子類。當僅需觸發一次或者以固定時間間隔週期執行,SimpleTrigger是最適合的選擇;而CronTrigger則可以通過Cron表示式定義出各種複雜時間規則的排程方案:如每早晨9:00執行,週一、週三、週五下午5:00執行等; Calendar:它是一些日曆特定時間點的集合。一個trigger可以包含多個Calendar,以便排除或包含某些時間點。 JobDetail

:用來描述Job實現類及其它相關的靜態資訊,如Job名字、關聯監聽器等資訊。在spring中有JobDetailFactoryBean和 MethodInvokingJobDetailFactoryBean兩種實現,如果任務排程只需要執行某個類的某個方法,就可以通過MethodInvokingJobDetailFactoryBean來呼叫。 Job:是一個介面,只有一個方法void execute(JobExecutionContext context),開發者實現該介面定義執行任務,JobExecutionContext類提供了排程上下文的各種資訊。Job執行時的資訊儲存在JobDataMap例項中。實現Job介面的任務,預設是無狀態的,若要將Job設定成有狀態的,在quartz中是給實現的Job新增@DisallowConcurrentExecution註解(以前是實現StatefulJob介面,現在已被Deprecated),在與spring結合中可以在spring配置檔案的job detail中配置concurrent引數。

2、Quartz特點

作為一個優秀的開源排程框架,Quartz 具有以下特點: 1、強大的排程功能,例如支援豐富多樣的排程方法,可以滿足各種常規及特殊需求; 2、靈活的應用方式,例如支援任務和排程的多種組合方式,支援排程資料的多種儲存方式; 3、分散式和叢集能力,Terracotta 收購後在原來功能基礎上作了進一步提升。 3、Quartz與Spring Task對比

applicationContext-task.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-autowire="byName" default-lazy-init="false"> <description>spring task定時任務</description> <!-- 定時任務配置 scheduler 方式 註解 暫時不支援動態更新 --> <context:component-scan base-package="com.sinoservices.task" /> <task:executor id="executor" pool-size="5" /> <task:scheduler id="scheduler" pool-size="10" /> <task:annotation-driven executor="executor" scheduler="scheduler" /> </beans>

定時任務執行類:使用@Scheduled進行配置,引數為corn表示式。

@Component
public class ActivityTimedTask {
   @Scheduled(cron = "0 0 */1 * * ?")
   public void getCarrayNo(){
	/** 業務邏輯 **/
   }
}

3.1 Quartz特性:

1、預設多執行緒非同步執行 2、單個任務時,在上一個排程未完成時,下一個排程時間到時,會另起一個執行緒開始新的排程。業務繁忙時,一個任務會有多個排程,可能導致資料處理異常。 3、多個任務時,任務之間沒有直接影響,多工執行的快慢取決於CPU的效能 4、觸發方式 SimpleTrigger:value=2000 每隔兩秒觸發 CronTrigger:value=”0 0 12 * * ?” 每天中午12點觸發(推薦) 5、需要在配置檔案中實現配置Job 6、能被叢集例項化,支援分散式部署 7、使用JobStoreCMT(JDBCJobStore的子類),Quartz 能參與JTA事務;Quartz 能管理JTA事務(開始和提交)在執行任務之間,這樣,任務做的事就可以發生在JTA事務裡。

3.2 Spring Task特性

1、預設單執行緒同步執行 2、單個任務時,當前次的排程完成後,再執行下一次任務排程 3、多個任務時,一個任務執行完成後才會執行下一個任務。若需要任務能夠併發執行,需手動設定執行緒池 4、觸發方式: 與Quartz的CronTrigger的表示式類似 5、可以使用註解標註定時任務

3.3對比

1、實現,Task註解實現方式,比較簡單。Quartz需要手動配置Jobs。 2、任務執行,Task預設單執行緒序列執行任務,多工時若某個任務執行時間過長,後續任務會無法及時執行。Quartz採用多執行緒,無這個問題。 3、排程,Task採用順序執行,若當前排程佔用時間過長,下一個排程無法及時執行; 4、Quartz採用非同步,下一個排程時間到達時,會另一個執行緒執行排程,不會發生阻塞問題,但排程過多時可能導致資料處理異常 5、部署,Quartz可以採用叢集方式,分散式部署到多臺機器,分配執行定時任務

4、專案搭建:

4.1執行SQL

你需要在資料庫中建立Quartz的相關係統表,所以你需要在資料庫中執行如下來自Quartz官方的指令碼。

-- in your Quartz properties file, you'll need to set org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-- 你需要在你的quartz.properties檔案中設定org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-- StdJDBCDelegate說明支援叢集,所有的任務資訊都會儲存到資料庫中,可以控制事物,還有就是如果應用伺服器關閉或者重啟,任務資訊都不會丟失,並且可以恢復因伺服器關閉或者重啟而導致執行失敗的任務
-- This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM
-- 這是來自quartz的指令碼,在MySQL資料庫中建立以下的表,修改為使用INNODB而不是MYISAM
-- 你需要在資料庫中執行以下的sql指令碼
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
-- 儲存每一個已配置的Job的詳細資訊
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
-- 儲存已配置的Trigger的資訊
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
-- 儲存已配置的Simple Trigger的資訊
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
-- 儲存Cron Trigger,包括Cron表示式和時區資訊
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    STR_PROP_1 VARCHAR(512) NULL,
    STR_PROP_2 VARCHAR(512) NULL,
    STR_PROP_3 VARCHAR(512) NULL,
    INT_PROP_1 INT NULL,
    INT_PROP_2 INT NULL,
    LONG_PROP_1 BIGINT NULL,
    LONG_PROP_2 BIGINT NULL,
    DEC_PROP_1 NUMERIC(13,4) NULL,
    DEC_PROP_2 NUMERIC(13,4) NULL,
    BOOL_PROP_1 VARCHAR(1) NULL,
    BOOL_PROP_2 VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
--  Trigger作為Blob型別儲存(用於Quartz使用者用JDBC建立他們自己定製的Trigger型別,JobStore並不知道如何儲存例項的時候)
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
-- 以Blob型別儲存Quartz的Calendar日曆資訊,quartz可配置一個日曆來指定一個時間範圍
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
-- 儲存已暫停的Trigger組的資訊
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
-- 儲存與已觸發的Trigger相關的狀態資訊,以及相聯Job的執行資訊
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
-- 儲存少量的有關 Scheduler的狀態資訊,和別的 Scheduler 例項(假如是用於一個叢集中)
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
-- 儲存程式的非觀鎖的資訊(假如使用了悲觀鎖)
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;

4.2表資訊解析

qrtz_blob_triggers : 以Blob型別儲存的觸發器。 qrtz_calendars:存放日曆資訊,quartz可配置一個日曆來指定一個時間範圍。 qrtz_cron_triggers:儲存CronTrigger,包括Cron表示式和時區資訊。 qrtz_fired_triggers:儲存與已觸發的Trigger相關的狀態資訊,以及相聯Job的執行資訊。 qrtz_job_details:存放一個jobDetail資訊。 qrtz_locks:儲存程式的悲觀鎖的資訊(假如使用了悲觀鎖)。 qrtz_paused_trigger_graps:存放暫停掉的觸發器。 qrtz_scheduler_state:排程器狀態。 qrtz_simple_triggers:簡單觸發器的資訊。 qrtz_trigger_listeners:觸發器監聽器。 qrtz_triggers:觸發器的基本資訊。 注意:cron方式需要用到的4張資料表: qrtz_triggers,qrtz_cron_triggers,qrtz_fired_triggers,qrtz_job_details。

4.3依賴新增

Springboot在2.X之後集成了Quartz框架。直接在pom.xml中新增以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

SpringBoot的1.X版本整合Quartz框架,新增一下依賴:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

4.4配置

4.4.1 建立quartz.properties配置檔案

#主要分為scheduler、threadPool、jobStore、plugin等部分
#ID設定為自動獲取 每一個必須不同 (所有排程器例項中是唯一的)
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
#指定排程程式的主執行緒是否應該是守護執行緒
org.quartz.scheduler.makeSchedulerThreadDaemon=true
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
# 例項化ThreadPool時,使用的執行緒類為SimpleThreadPool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#ThreadPool配置執行緒守護程序
org.quartz.threadPool.makeThreadsDaemons=true
# threadCount和threadPriority將以setter的形式注入ThreadPool例項
# 併發個數
org.quartz.threadPool.threadCount=5
# 優先順序
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
#容許的最大作業延長時間
org.quartz.jobStore.misfireThreshold=5000

#資料儲存方式為持久化
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#StdJDBCDelegate說明支援叢集
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#是否加入叢集
org.quartz.jobStore.isClustered=true
# 預設儲存在記憶體中
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#持久化
org.quartz.dataSource.myDS.connectionProvider.class=com.esgcc.wlzx.scheduledwar.database.DruidConnectionProvider
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.dataSource=myDS
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL=@org.quartz.dataSource.myDS.[email protected]
org.quartz.dataSource.myDS.user=@org.