JAVA:Spring Boot 集成 Quartz 实现分布式任务

admin
0
2025-10-11

1、简述

Quartz 是一个强大的任务调度框架,允许开发者在应用程序中定义和执行定时任务。在 Spring Boot 中集成 Quartz,可以轻松实现任务的调度、管理、暂停和恢复等功能。在分布式系统中,Quartz 也支持集群化的任务调度,确保任务的高可用性和一致性。本文将介绍如何在 Spring Boot 中集成 Quartz,并展示分布式任务调度的样例。

image-47qx.png


2、添加 Quartz 依赖

Quartz 是一个开源的 Java 定时任务调度框架,它可以帮助我们:

🔹 定时执行任务,如定时清理数据、邮件通知等。

🔹 在复杂的时间规则下灵活调度任务。

🔹 支持持久化调度,任务状态可以存储在数据库中,支持任务的恢复与重启。

🔹 在分布式环境下,可以实现任务的集群调度。

image-3i7n.png

在 Spring Boot 中集成 Quartz,首先需要在 pom.xml 中引入 Quartz 的依赖:

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

这个依赖包含了 Spring Boot 对 Quartz 的自动配置支持,帮助我们快速实现定时任务调度。


3、实践样例

3.1 配置 Quartz

在 Spring Boot 项目中,可以通过配置文件来设置 Quartz 的相关属性。这里是一个简单的 Quartz 配置示例:

spring:
  quartz:
    job-store-type: jdbc  # 使用 JDBC 存储任务
    jdbc:
      initialize-schema: always  # 自动初始化数据库表
    properties:
      org:
        quartz:
          scheduler:
            instanceName: MyClusteredScheduler
            instanceId: AUTO  # 自动生成实例ID
          threadPool:
            threadCount: 10  # 调度线程数
          jobStore:
            isClustered: true  # 启用集群
            clusterCheckinInterval: 20000  # 集群节点检查间隔
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # 数据库操作类

🔹 job-store-type: jdbc 表示使用 JDBC 方式来持久化任务和触发器,确保在应用重启或宕机后任务能够恢复。

🔹 isClustered: true 表示启用了 Quartz 集群模式,支持多节点协调任务调度。

3.2 初始化数据库表

Quartz 使用 JDBC 模式时需要有数据库表来存储任务和触发器。你可以通过执行官方的 SQL 脚本来创建这些表,具体 SQL 脚本可以从 Quartz 官方 GitHub 获取。

对于 MySQL 数据库,可以在项目中执行 quartz_tables_mysql.sql:

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)
);
-- 其他表略

3.3 定义 Quartz Job 和触发器

在 Quartz 中,任务(Job)是调度的最小单位,触发器(Trigger)决定了任务何时执行。我们首先需要定义一个简单的 Job,例如一个打印日志的任务:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleJob implements Job {
    private static final Logger logger = LoggerFactory.getLogger(SimpleJob.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.info("执行定时任务:SimpleJob - {}", System.currentTimeMillis());
    }
}

接下来,为这个任务创建一个触发器。在 Spring 中,我们可以使用 JobDetail 和 Trigger 来定义:

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail simpleJobDetail() {
        return JobBuilder.newJob(SimpleJob.class)
                .withIdentity("simpleJob")
                .storeDurably()  // 即使没有触发器关联时,也保留该任务
                .build();
    }

    @Bean
    public Trigger simpleJobTrigger() {
        return TriggerBuilder.newTrigger()
                .forJob(simpleJobDetail())
                .withIdentity("simpleTrigger")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(10)  // 每10秒执行一次
                        .repeatForever())
                .build();
    }
}

在这个配置中,JobDetail 定义了 SimpleJob 的细节,Trigger 定义了任务每 10 秒执行一次。

3.4 定时器启动

创建定时器手动启动定时器任务,执行SimpleJob 任务。

package com.lm.quartz.config;

import com.lm.quartz.job.SimpleJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzManualConfig implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        // 创建 Scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 定义 Job
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("simpleJob", "group1")
                .build();

        // 定义 Trigger
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("simpleTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(5)
                        .repeatForever())
                .build();

        // 调度 Job
        scheduler.scheduleJob(jobDetail, trigger);

        // 手动启动
        scheduler.start();

        System.out.println("✅ Quartz 已手动启动...");
    }
}

3.5 Quartz 集群的配置

为了在分布式环境中实现 Quartz 的集群调度,除了上述的 JDBC 持久化配置外,还需要在不同的节点上配置相同的数据库和 Quartz 配置。这些节点可以同时运行,当一个节点失效时,另一个节点将接管其任务。Quartz 通过数据库锁来确保任务只在一个节点上执行。

在每个节点上,只需确保:

🔹 使用相同的 Quartz 数据库配置。

🔹 保持 isClustered: true。

🔹 配置唯一的 instanceId(可以使用 AUTO 自动生成)。

假设我们有两个微服务实例,它们共同调度同一个任务。在这两个实例上,只需要共享同一个数据库,同时启用集群模式:

spring:
  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: never  # 数据库表已经在某个节点初始化
    properties:
      org:
        quartz:
          scheduler:
            instanceName: ClusteredSchedulerNode1  # 每个节点需要唯一的实例名称
            instanceId: AUTO
          jobStore:
            isClustered: true
            clusterCheckinInterval: 20000

启动多个服务实例后,Quartz 会自动协调各个节点的任务调度。在某个节点失效时,其他节点会接管其任务,确保任务调度的高可用性。

3.6 日志与监控

为了更好地了解 Quartz 的运行状态,可以通过日志来监控任务的执行情况。Spring Boot 提供了良好的日志管理机制,开发者可以在 application.yml 中配置日志级别:

logging:
  level:
    org.quartz: DEBUG

此外,可以通过集成 Spring Boot Actuator 来监控 Quartz 的运行状态和任务调度情况。


4、总结

通过集成 Quartz,Spring Boot 项目可以轻松实现任务调度功能,并且在分布式环境中支持任务的集群化调度。本文详细介绍了 Quartz 的基本配置、任务调度示例,以及如何在分布式系统中使用 Quartz 实现高可用的任务调度。希望本文能帮助你在项目中顺利使用 Quartz 来管理和调度定时任务。

动物装饰