什麼是quartz?
Quartz是一個完全由 Java 編寫的開源任務排程架構。
我們經常會遇到一些問題:
想每個月27号,提醒信用卡還款;
想每隔1小時,提醒一下,累了,站起來活動一下;
想每個月定時發送郵件,等等。
總結起來就是,在一個有規律的時間點做某件事。
quartz可滿足複雜觸發條件下的定時任務排程,比如每月的周一和周五 10點 15分執行。
quartz叢集可保證系統的高可用性,即使一個節點崩了,也能保證任務的執行。
叢集環境下,一個任務某個時間點隻會在一個節點上運作。
核心概念
- Job 表示一個工作,要執行的具體内容
- JobDetail 表示任務的定義,Job 是任務的執行邏輯
- Trigger 代表一個排程參數的配置,什麼時候去調
- Scheduler 代表一個排程容器,一個排程容器中可以注冊多個 JobDetail 和 Trigger。當 Trigger 與 JobDetail 組合,就可以被 Scheduler 容器排程了。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iYkNDNldzYjJDMmJ2N1Q2MiBDMiBTO2EWN1MGO2ITZ38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
quartz叢集應用
叢集中的節點放在不同的伺服器上,稱為水準叢集。
節點放在同一台機器上,稱為垂直叢集,存在着單點故障問題。
Quartz可以借助關系資料庫和JDBC作業存儲支援叢集。
資料庫腳本
連結:https://pan.baidu.com/s/1BpDTVRwtN6_VVJqTx9flNQ
提取碼:49ie
搭建spring boot環境
以定時發送郵件為例,每隔1分鐘發送一次,郵件發送功能忽略,不是本例重點。
開發工具:Intellij IDEA
添加maven 依賴
配置
- 配置application.yml
server: port: ${PORT:8090}spring: application: name: learn-quartz datasource: druid: url: ${MYSQL_URL:jdbc:mysql://192.168.0.113:3306/quartz?characterEncoding=utf-8&useSSL=false} username: root password: 123456 driverClassName: com.mysql.cj.jdbc.Driver initialSize: 5 #初始建立連接配接數量 minIdle: 5 #最小連接配接數量 maxActive: 20 #最大連接配接數量 maxWait: 10000 #擷取連接配接最大等待時間,毫秒 testOnBorrow: true #申請連接配接時檢測連接配接是否有效 testOnReturn: false #歸還連接配接時檢測連接配接是否有效 timeBetweenEvictionRunsMillis: 60000 #配置間隔檢測連接配接是否有效的時間(機關是毫秒) minEvictableIdleTimeMillis: 300000 #連接配接在連接配接池的最小生存時間(毫秒) quartz: job-store-type: jdbc #資料庫方式 jdbc: initialize-schema: never #不初始化表結構 properties: org: quartz: scheduler: instanceId: AUTO #預設主機名和時間戳生成執行個體ID,可以是任何字元串,但對于所有排程程式來說,必須是唯一的 對應qrtz_scheduler_state INSTANCE_NAME字段 instanceName: clusteredScheduler #quartzScheduler jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX #持久化配置 driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #我們僅為資料庫制作了特定于資料庫的代理 useProperties: false #以訓示JDBCJobStore将JobDataMaps中的所有值都作為字元串,是以可以作為名稱 - 值對存儲而不是在BLOB列中以其序列化形式存儲更多複雜的對象。從長遠來看,這是更安全的,因為您避免了将非String類序列化為BLOB的類版本問題。 tablePrefix: QRTZ_ #資料庫表字首 misfireThreshold: 60000 #在被認為“失火”之前,排程程式将“容忍”一個Triggers将其下一個啟動時間通過的毫秒數。預設值(如果您在配置中未輸入此屬性)為60000(60秒)。 clusterCheckinInterval: 5000 #設定此執行個體“檢入”*與群集的其他執行個體的頻率(以毫秒為機關)。影響檢測失敗執行個體的速度。 isClustered: true #打開群集功能 threadPool: #連接配接池 class: org.quartz.simpl.SimpleThreadPool threadCount: 10 threadPriority: 5 threadsInheritContextClassLoaderOfInitializingThread: true
- 定義Job
public class EmailJob extends QuartzJobBean { @Value("${server.port}") String port; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { String time = DateUtil.now(); System.out.println(time + " send email,server port:" + port); }}
- 配置QuartzConfig.java
@Configurationpublic class QuartzConfig { @Bean public JobDetail jobSendEmailDetails() { return JobBuilder.newJob(EmailJob.class).withIdentity("emailJobId") .storeDurably().build(); } /** * 1分鐘1次,會平均配置設定到每個節點上 * @return */ @Bean public Trigger jobOrderCheckTrigger() { return TriggerBuilder.newTrigger().forJob(jobSendEmailDetails()) .withIdentity("sendEmailTriggerId") .withSchedule(CronScheduleBuilder.cronSchedule("0 0/1 * * * ?")) .build(); }}
建立2個應用
選擇Edit Configurations, 在spring boot目錄下建立quartz1和quartz2, VM options中分别輸入-DPORT=8090和-DPORT=8091, 啟動兩個執行個體,同一個任務會在兩個執行個體中輪流執行,效果圖:
quartz1
quartz2