【第38章】Spring Cloud之Quartz分布式任务调度
文章目录
- 前言
- 一、准备
- 1. 引入依赖
- 2. 新建quartz库
- 3. Spring Bean
- 二、核心代码和配置
- 1. 核心代码
- 1.1 定义JobFactory
- 1.2 定义SchedulerFactory
- 1.3 定义Job
- 2. 核心配置
- 2.1 配置quartz.properties
- 2.2 配置quartz_data.xml
- 三、单元测试
- 1. 准备
- 2. 日志记录
- 总结
前言
Quartz是一个功能丰富的开源作业调度库,可以集成在几乎任何Java应用程序中,从最小的独立应用程序到最大的电子商务系统。
一、准备
1. 引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.transaction/jta -->
<dependency><groupId>javax.transaction</groupId><artifactId>jta</artifactId><version>1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.5</version>
</dependency>
2. 新建quartz库
CREATE DATABASE quartz;
CREATE USER 'quartz'@'%' IDENTIFIED BY 'quartz';
GRANT ALL PRIVILEGES ON quartz.* TO 'quartz'@'%';
FLUSH PRIVILEGES;
use quartz;
在
org.quartz.impl.jdbcjobstore下找到对应的sql文件,我这里使用的mysql

3. Spring Bean
-
JobDetail: 定义特定作业。JobDetail实例可以使用JobBuilder API构建。
-
Calendar.
-
Trigger: 定义何时触发特定作业。
二、核心代码和配置
1. 核心代码
1.1 定义JobFactory
package org.example.nacos.consumer.quartz;import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component;/*** Create by zjg on 2024/9/22*/
@Component
public class QuartzJobFactory extends SpringBeanJobFactory {@Autowiredprivate AutowireCapableBeanFactory capableBeanFactory;@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception{Object jobInstance = super.createJobInstance(bundle);capableBeanFactory.autowireBean(jobInstance);return jobInstance;}
}
1.2 定义SchedulerFactory
package org.example.nacos.consumer.quartz;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;/*** Create by zjg on 2024/9/22*/
@Configuration
public class QuartzConfig {@Autowiredprivate QuartzJobFactory quartzJobFactory;@Beanpublic SchedulerFactoryBean schedulerFactoryBean(){SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));schedulerFactoryBean.setJobFactory(quartzJobFactory);return schedulerFactoryBean;}
}
1.3 定义Job
package org.example.nacos.consumer.quartz;import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;/*** Create by zjg on 2024/9/22*/
@Component
public class SimpleJob implements Job {Logger logger = LoggerFactory.getLogger(SimpleJob.class);@Autowiredprivate ApplicationContext applicationContext;@Value("${server.port}")private int port;@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {String name = applicationContext.getEnvironment().getProperty("spring.application.name");logger.debug(name+"-"+port+":SpringCloudJob1-----执行");}
}
2. 核心配置
2.1 配置quartz.properties
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName=SpringCloudScheduler
org.quartz.scheduler.instanceId=AUTO#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=5
org.quartz.threadPool.threadPriority=5#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://192.168.145.128:3306/quartz
org.quartz.dataSource.myDS.user=quartz
org.quartz.dataSource.myDS.password=quartz
org.quartz.dataSource.myDS.maxConnections=5
org.quartz.dataSource.myDS.validationQuery=select 0#============================================================================
# Configure Plugins
#============================================================================
org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames=quartz_data.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound=true
org.quartz.plugin.jobInitializer.scanInterval=120
org.quartz.plugin.jobInitializer.wrapInUserTransaction=false
2.2 配置quartz_data.xml
<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"version="1.8"><processing-directives><!-- if there are any jobs/trigger in scheduler of same name (as in this file), overwrite them --><overwrite-existing-data>true</overwrite-existing-data><!-- if there are any jobs/trigger in scheduler of same name (as in this file), and over-write is false, ignore them rather then generating an error --><ignore-duplicates>false</ignore-duplicates></processing-directives><schedule><job><name>SpringCloudJob1</name><group>SpringCloud</group><job-class>org.example.nacos.consumer.quartz.SimpleJob</job-class></job><trigger><cron><name>SpringCloudTrigger1</name><group>SpringCloudTrigger</group><job-name>SpringCloudJob1</job-name><job-group>SpringCloud</job-group><job-data-map><entry><key>someKey</key><value>overriddenValue</value></entry><entry><key>someOtherKey</key><value>someOtherOverriddenValue</value></entry></job-data-map><cron-expression>0 * * ? * *</cron-expression></cron></trigger></schedule>
</job-scheduling-data>
三、单元测试
我们上面的cron表达式定义的是每分钟执行一次,并打印程序信息记录日志。
1. 准备
我们启动3台消费者服务作为一个集群,根据不同端口号区分服务

2. 日志记录
我们先观察个10分钟的,随后分析具体的执行情况。
2024-09-22 17:00:00.008 [TID: N/A] DEBUG 14312 [consumer-service] [eduler_Worker-3] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9005:SpringCloudJob1-----执行
2024-09-22 17:01:00.011 [TID:N/A] DEBUG 12424 [consumer-service] [eduler_Worker-3] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9003:SpringCloudJob1-----执行
2024-09-22 17:02:00.007 [TID: N/A] DEBUG 1816 [consumer-service] [eduler_Worker-2] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9004:SpringCloudJob1-----执行
2024-09-22 17:03:00.011 [TID: N/A] DEBUG 14312 [consumer-service] [eduler_Worker-4] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9005:SpringCloudJob1-----执行
2024-09-22 17:04:00.009 [TID:N/A] DEBUG 12424 [consumer-service] [eduler_Worker-5] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9003:SpringCloudJob1-----执行
2024-09-22 17:05:00.008 [TID: N/A] DEBUG 1816 [consumer-service] [eduler_Worker-4] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9004:SpringCloudJob1-----执行
2024-09-22 17:06:00.007 [TID:N/A] DEBUG 12424 [consumer-service] [eduler_Worker-2] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9003:SpringCloudJob1-----执行
2024-09-22 17:07:00.009 [TID: N/A] DEBUG 14312 [consumer-service] [eduler_Worker-5] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9005:SpringCloudJob1-----执行
2024-09-22 17:08:00.009 [TID:N/A] DEBUG 12424 [consumer-service] [eduler_Worker-3] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9003:SpringCloudJob1-----执行
2024-09-22 17:09:00.109 [TID:N/A] DEBUG 12424 [consumer-service] [eduler_Worker-4] o.e.nacos.consumer.quartz.SimpleJob :27 : consumer-service-9003:SpringCloudJob1-----执行
我按照时间进行排序,通过端口号可以看出三台服务器都有执行,且同一时间段的这个任务只有一个服务节点去执行了,Quartz可以非常轻松的完成我们的日常作业调度需求,非常完美。
总结
回到顶部
官方网站
项目源码
快速开始
官方案例
quartz的用法还有很多,大家可以自行研究,另外在这里给大家推荐下XXL-JOB,这是一款国产的分布式任务调度平台,我后面有时间的话可能会开专栏学习它。
