首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Quartz 任務調度框架:從入門到生產級實戰全解析

     編輯:Java 相關知識

為什麼需要 Quartz?

當應用需要:「每天凌晨 2 點跑對帳」、「每 5 分鐘同步第三方數據」、「每月最後一天發薪資單」—— 別再寫 while(true){sleep();} 了。**Quartz** 是成熟、開源、純 Java 的企業級任務調度框架,支援叢集、持久化、Cron 表達式、監聽器、插件化擴充,已被 Spring Boot、Elasticsearch、Kubernetes 等知名專案廣泛採用。

核心概念三支柱

組件職責關鍵介面/類
Job (作業)業務邏輯載體org.quartz.Job (單一方法 execute(JobExecutionContext))
Trigger (觸發器)定義「何時跑」SimpleTrigger (間隔/次數), CronTrigger (Cron 表達式)
Scheduler (調度器)核心引擎,管理 Job/Trigger 生命週期、執行緒池、持久化org.quartz.Scheduler, StdSchedulerFactory

五分鐘快速上手

1. 依賴 (Maven)

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>
<!-- Spring Boot 整合更簡單:spring-boot-starter-quartz -->

2. 定義 Job

@Slf4j
@DisallowConcurrentExecution // 禁止併發執行同一 Job 實例 (對應 StatefulJob)
public class FtpSyncJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap dataMap = context.getMergedJobDataMap();
        String ftpHost = dataMap.getString("ftpHost");
        int port = dataMap.getInt("port");
        // 業務邏輯:連線 FTP、下載檔案、解析入庫、發送通知...
        log.info("FTP 同步完成: host={}, port={}", ftpHost, port);
    }
}

3. 程式化調度 (Java Config)

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail ftpSyncJobDetail() {
        return JobBuilder.newJob(FtpSyncJob.class)
                .withIdentity("ftpSyncJob", "syncGroup")
                .usingJobData("ftpHost", "files.example.com")
                .usingJobData("port", 21)
                .storeDurably() // 無 Trigger 也保留
                .build();
    }

    @Bean
    public Trigger ftpSyncTrigger(JobDetail ftpSyncJobDetail) {
        // 每天 02:00 執行
        return TriggerBuilder.newTrigger()
                .forJob(ftpSyncJobDetail)
                .withIdentity("ftpSyncTrigger", "syncGroup")
                .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(2, 0))
                .build();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger ftpSyncTrigger, JobDetail ftpSyncJobDetail) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setTriggers(ftpSyncTrigger);
        factory.setJobDetails(ftpSyncJobDetail);
        factory.setOverwriteExistingJobs(true);
        factory.setStartupDelay(30); // 應用啟動 30 秒後啟動調度器
        return factory;
    }
}

4. 宣告式調度 (XML/資料庫)

生產環境建議將 Job/Trigger 定義外部化至資料庫 (JDBC JobStore),支援動態新增/修改/暫停/刪除任務,無需重新部署。Spring Boot 整合 Quartz 只需配置 spring.quartz.job-store-type=jdbc 並提供 DataSource,自動建表腳本在 org/quartz/impl/jdbcjobtables/。

進階特性深度解析

1. JobStore:持久化策略選型

**生產必選 JDBC JobStore + 叢集模式** (設定 org.quartz.jobStore.isClustered=true),多節點共享同一資料庫,自動負載均衡與故障轉移。

2. CronTrigger 表達式詳解

秒 分 時 日 月 星期 年(可選)
*  *  *  *  *  ?   *     → 每秒
0  0  12 ?  *  *   *     → 每天中午 12:00
0  15 10 ?  *  MON-FRI * → 工作天 10:15
0  0  0  L  *  ?   *     → 每月最後一天午夜
0  15 10 ?  *  6L  *    → 每月最後一個週五 10:15
0  0  12 1/5 *  ?   *    → 每月 1 號起每 5 天中午 12:00

線上驗證工具:crontab.guru (注意 Quartz 為 6/7 欄位,標準 Cron 為 5 欄位)。

3. 監聽器:解耦橫切關注點

  • JobListener:Job 執行前/後/失敗/被拒絕 — 記錄審計日誌、發送告警、執行時間統計。
  • TriggerListener:Trigger 觸發/錯過/完成 — 動態調整下次觸發時間。
  • SchedulerListener:調度器啟動/關閉/暫停/恢復 — 生命週期管理。
public class AuditJobListener implements JobListener {
    @Override public String getName() { return "auditListener"; }
    @Override public void jobWasExecuted(JobExecutionContext ctx, JobExecutionException e) {
        long duration = System.currentTimeMillis() - ctx.getFireTime().getTime();
        log.info("Job [{}] 耗時 {}ms, 結果: {}", ctx.getJobDetail().getKey(), duration, e == null ? "成功" : "失敗: " + e.getMessage());
    }
    // 其他方法...
}

4. 叢集與高可用

  • 所有節點共享同一資料庫、同一 org.quartz.scheduler.instanceName、instanceId=AUTO。
  • 資料庫表 QRTZ_LOCKS 實現分散式鎖,保證同一任務同一時間只在單節點執行。
  • 節點心跳機制 (clusterCheckinInterval 預設 15s) 偵測失效節點,自動接管其任務。

5. 插件化擴充

  • JobInitializerPlugin:啟動時從 XML/資源檔載入 Job/Trigger。
  • ShutdownHookPlugin:JVM 關閉時優雅停止 Scheduler。
  • 自訂 Plugin 實作 org.quartz.spi.SchedulerPlugin,注入 Spring Bean、整合監控系統。

Web 管理控制台

別只靠日誌查任務。**Quartz UI** 專案 (GitHub) 提供 Spring Boot 整合的前端介面:任務增刪改查、觸發器狀態、執行歷史、手動觸發/暫停/恢復、Cron 表達式可視化編輯器。生產環境建議加上 Spring Security 權限控制。

常見坑與最佳實踐

  1. Job 類無狀態:預設無狀態,叢集下每次觸發新建實例。需跨執行共享資料 → 用 JobDataMap (序列化) 或外部快取 (Redis)。
  2. 避免長耗時 Job 阻塞執行緒池:org.quartz.threadPool.threadCount 預設 10-20。長任務拋到非同步佇列 (CompletableFuture/ExecutorService) 或用單獨執行緒池。
  3. 錯過觸發處理:misfireThreshold (預設 60s) + MisfireInstruction (如 FIRE_ONCE_NOW, DO_NOTHING) 定義補償策略。
  4. 事務邊界:Job 內業務用 @Transactional 獨立管理,不要依賴 Quartz 事務。
  5. 版本升級:Quartz 2.x → 3.x API 變動大 (Package 變更、Java 8+ 基線),升級前跑完整測試。

替代方案對比

類型適用場景優/缺點
RAMJobStore開發、測試、單節點、任務少、可容忍重啟丟失極快、零配置 / 非持久、無法叢集
JobStoreTX獨立應用、自管事務持久化、支援叢集 / 需資料庫、效能稍低
JobStoreCMTJava EE 容器、容器管事務 (JTA)整合容器事務 / 配置複雜
框架定位優勢劣勢
Quartz通用調度、叢集、持久化成熟穩定、Spring 整合深、功能全API 略顯老舊、配置相對繁瑣
Spring @Scheduled輕量級、單體應用零配置、註解驅動、Spring 原生無持久化、無叢集、無動態管理、單點故障
XXL-JOB分散式任務調度平台Web 控制台、分片廣播、故障轉移、多語言需部署獨立調度中心、學習成本
Elastic-Job分散式叢集調度基於 Quartz/ZK、分片彈性、運維平台社區活躍度下降、ShardingSphere 整合為主

選型建議:單體/微服務少量定時任務 → @Scheduled;需持久化、叢集、動態管理、審計 → **Quartz**;大規模分散式、運維平台化、多語言 → **XXL-JOB / PowerJob**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved