【详解】Springquartz集群(MySQL数据源)

举报
皮牙子抓饭 发表于 2025/01/22 21:31:06 2025/01/22
【摘要】 Spring Quartz 集群 (MySQL 数据源)简介Quartz 是一个功能强大的调度库,可以在 Java 应用中用于执行定时任务。在单机环境中,Quartz 的配置和使用相对简单,但在分布式系统中,为了确保任务的唯一性和高可用性,通常需要将 Quartz 配置为集群模式。本文将介绍如何在 Spring 框架下配置 Quartz 集群,并使用 MySQL 作为数据源来存储调度信息。环...

Spring Quartz 集群 (MySQL 数据源)

简介

Quartz 是一个功能强大的调度库,可以在 Java 应用中用于执行定时任务。在单机环境中,Quartz 的配置和使用相对简单,但在分布式系统中,为了确保任务的唯一性和高可用性,通常需要将 Quartz 配置为集群模式。本文将介绍如何在 Spring 框架下配置 Quartz 集群,并使用 MySQL 作为数据源来存储调度信息。

环境准备

  • Java 版本: 1.8 或更高
  • Spring Boot 版本: 2.3.x
  • Quartz 版本: 2.3.x
  • 数据库: MySQL 5.7 或更高

步骤一:添加依赖

首先,在 ​​pom.xml​​ 文件中添加 Spring Boot 和 Quartz 的依赖:

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

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

    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>

步骤二:配置数据库

在 ​​application.properties​​ 中配置数据库连接:

spring.datasource.url=jdbc:mysql://localhost:3306/quartz?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

步骤三:创建 Quartz 表

Quartz 需要一些特定的表来存储调度信息。可以使用 Quartz 提供的 SQL 脚本来创建这些表。对于 MySQL,可以使用 ​​tables_mysql_innodb.sql​​ 脚本。

将脚本中的 SQL 语句执行到 MySQL 数据库中:

-- 示例:创建 Quartz 表
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;

-- 其他表创建语句...

步骤四:配置 Quartz 集群

在 ​​application.properties​​ 中配置 Quartz 以启用集群模式:

# Quartz 配置
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.quartz.properties.org.quartz.scheduler.instanceName=ClusteredScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_

步骤五:创建任务

定义一个简单的 Quartz 任务类:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class SimpleJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("SimpleJob is running...");
    }
}

步骤六:配置任务调度

在 Spring 配置类中配置任务调度:

import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(SimpleJob.class);
        factoryBean.setDurability(true);
        return factoryBean;
    }

    @Bean
    public SimpleTriggerFactoryBean trigger(JobDetail jobDetail) {
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetail);
        factoryBean.setRepeatInterval(10000); // 每10秒执行一次
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        factoryBean.setStartDelay(0L);
        factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT);
        return factoryBean;
    }
}

步骤七:启动应用

启动 Spring Boot 应用程序,Quartz 将自动在集群模式下运行,并且所有节点都会共享相同的调度信息。


参考资料


Spring Quartz 是一个非常流行的调度框架,用于在Java应用程序中执行定时任务。当使用Quartz与Spring框架结合时,可以通过配置MySQL作为数据源来实现集群化部署,从而确保高可用性和负载均衡。

下面是一个简单的示例,展示如何在Spring Boot项目中配置和使用Spring Quartz集群(使用MySQL作为数据源):

1. 添加依赖

首先,在​​pom.xml​​文件中添加Spring Boot、Quartz和MySQL的依赖:

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

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

    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- HikariCP Connection Pool -->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
</dependencies>

2. 配置MySQL数据源

在​​application.properties​​或​​application.yml​​中配置MySQL数据源和Quartz的相关属性:

# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/quartz_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# HikariCP连接池配置
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.maximum-pool-size=10

# Quartz配置
spring.quartz.job-store-type=jdbc
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
spring.quartz.properties.org.quartz.scheduler.instanceName=ClusteredScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO

3. 创建Quartz Job

创建一个简单的Quartz Job类,该类实现了​​Job​​接口:

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

public class MyJob implements Job {

    private static final Logger logger = LoggerFactory.getLogger(MyJob.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        logger.info("Executing job at: " + new java.util.Date());
    }
}

4. 配置Quartz Job和Trigger

在Spring Boot的配置类中定义Quartz Job和Trigger:

import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(MyJob.class);
        factoryBean.setDurability(true);
        return factoryBean;
    }

    @Bean
    public SimpleTriggerFactoryBean trigger(JobDetail jobDetail) {
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetail);
        factoryBean.setRepeatInterval(10000); // 每10秒执行一次
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        factoryBean.setStartDelay(0);
        factoryBean.setMisfireInstruction(SimpleScheduleBuilder.MISFIRE_INSTRUCTION_FIRE_NOW);
        return factoryBean;
    }
}

5. 启动Spring Boot应用

最后,创建一个Spring Boot启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class QuartzClusterApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuartzClusterApplication.class, args);
    }
}

6. 初始化Quartz表

确保在MySQL数据库中创建Quartz所需的表。可以使用Quartz提供的SQL脚本,通常位于Quartz的发行包中,或者从Quartz的GitHub仓库下载。

例如,使用以下命令创建表:

CREATE DATABASE quartz_db;
USE quartz_db;

-- 运行Quartz提供的SQL脚本
SOURCE path/to/tables_mysql_innodb.sql;

7. 测试

启动多个实例(每个实例运行在不同的端口上),观察日志输出,确保任务在集群中的不同节点上交替执行。

以上就是一个完整的Spring Boot + Quartz + MySQL集群配置示例。希望对你有所帮助!如果有任何问题或需要进一步的帮助,请随时告诉我。在使用Spring与Quartz结合构建定时任务的集群环境中,MySQL通常被用作持久化存储来确保任务的调度信息能够在集群中的不同节点间共享。这样可以避免同一个任务在多个节点上重复执行,并且能够保证即使某个节点宕机,其他节点也能接管未完成的任务。

以下是一个详细的步骤和示例代码,介绍如何在Spring Boot项目中配置和使用Quartz集群(MySQL数据源):

1. 添加依赖

首先,在​​pom.xml​​文件中添加Spring Boot和Quartz的相关依赖:

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

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

    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>

2. 配置Quartz

在​​application.properties​​或​​application.yml​​中配置Quartz连接到MySQL数据库:

# MySQL 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/quartz?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Quartz 配置
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.quartz.properties.org.quartz.scheduler.instanceName=ClusteredScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=10

3. 创建定时任务

创建一个简单的定时任务类:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {

    @Override
 public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob is running on node " + context.getScheduler().getSchedulerInstanceId());
    }
}

4. 配置Spring Boot启动类

在Spring Boot的启动类中配置Quartz Scheduler:

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class QuartzInitializer implements CommandLineRunner {

    @Autowired
    private SchedulerFactory schedulerFactory;

    @Override
    public void run(String... args) throws Exception {
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();
    }

    @Bean
    public SchedulerFactory schedulerFactory() {
        return new StdSchedulerFactory();
    }
}

5. 定义Job和Trigger

使用Spring的​​@Configuration​​类来定义Job和Trigger:

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail myJobDetail() {
        return JobBuilder.newJob(MyJob.class)
                .withIdentity("myJob", "group1")
                .build();
    }

    @Bean
    public Trigger myJobTrigger() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)
                .repeatForever();

        return TriggerBuilder.newTrigger()
                .forJob(myJobDetail())
                .withIdentity("myJobTrigger", "group1")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

6. 启动应用

启动Spring Boot应用后,Quartz会根据配置自动创建并调度任务。由于配置了集群模式,多个节点上的应用会共享相同的任务调度信息,确保任务不会重复执行。

注意事项

  1. 数据库表结构:确保MySQL数据库中有Quartz所需的表结构。可以通过设置​​spring.quartz.jdbc.initialize-schema=always​​来自动生成这些表。
  2. 集群配置:确保每个节点的​​instanceId​​是唯一的,可以通过设置​​AUTO​​来自动生成。
  3. 时间同步:确保集群中的所有节点的时间同步,以避免因时间不一致导致的任务调度问题。

通过以上步骤,你可以在Spring Boot项目中成功配置和使用Quartz集群(MySQL数据源)。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。