SpringBoot与Quartz集成实现分布式定时任务集群的代码实例

Spring Boot与Quartz集成实现分布式定时任务集群

直接贴代码

POM

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>test.daemon</groupId>

<artifactId>clusterquartz</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>jar</packaging>

<name>clusterquartz</name>

<url>http://maven.apache.org</url>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.4.1.RELEASE</version>

<relativePath />

</parent>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-logging</artifactId>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.0.13</version>

</dependency>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

</dependency>

<dependency>

<groupId>org.quartz-scheduler</groupId>

<artifactId>quartz</artifactId>

<version>2.2.1</version>

</dependency>

<dependency>

<groupId>org.quartz-scheduler</groupId>

<artifactId>quartz-jobs</artifactId>

<version>2.2.1</version>

</dependency>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

</project>

application.yml

server:

port: 80

spring:

datasource:

url: jdbc:mysql://localhost:3306/quartz

username: admin

password: admin

driver-class-name: com.mysql.jdbc.Driver

quartz.properties

#============================================================================

# Configure JobStore

# Using Spring datasource in SchedulerConfig.java

# Spring uses LocalDataSourceJobStore extension of JobStoreCMT

#============================================================================

org.quartz.jobStore.useProperties=false

org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.isClustered = true

org.quartz.jobStore.clusterCheckinInterval = 5000

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.txIsolationLevelReadCommitted = true

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

#============================================================================

# Configure Main Scheduler Properties

# Needed to manage cluster instances

#============================================================================

org.quartz.scheduler.instanceName = ClusterQuartz

org.quartz.scheduler.instanceId= AUTO

org.quartz.scheduler.rmi.export = false

org.quartz.scheduler.rmi.proxy = false

org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================

# Configure ThreadPool

# Can also be configured in spring configuration

#============================================================================

#org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

#org.quartz.threadPool.threadCount = 5

#org.quartz.threadPool.threadPriority = 5

#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

Spring配置类

package test.daemon.clusterquartz.config;

import java.io.IOException;

import java.util.Properties;

import java.util.concurrent.Executor;

import javax.sql.DataSource;

import org.quartz.Scheduler;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.config.PropertiesFactoryBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.ClassPathResource;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import org.springframework.scheduling.quartz.CronTriggerFactoryBean;

import org.springframework.scheduling.quartz.JobDetailFactoryBean;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import test.daemon.clusterquartz.quartz.QuartzJob;

@Configuration

public class SchedulerConfig {

@Autowired

private DataSource dataSource;

@Bean

public Scheduler scheduler() throws Exception {

Scheduler scheduler = schedulerFactoryBean().getScheduler();

scheduler.start();

return scheduler;

}

@Bean

public SchedulerFactoryBean schedulerFactoryBean() throws IOException {

SchedulerFactoryBean factory = new SchedulerFactoryBean();

factory.setSchedulerName("Cluster_Scheduler");

factory.setDataSource(dataSource);

factory.setApplicationContextSchedulerContextKey("applicationContext");

factory.setTaskExecutor(schedulerThreadPool());

factory.setTriggers(trigger1().getObject());

factory.setQuartzProperties(quartzProperties());

return factory;

}

@Bean

public Properties quartzProperties() throws IOException {

PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();

propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));

// 在quartz.properties中的属性被读取并注入后再初始化对象

propertiesFactoryBean.afterPropertiesSet();

return propertiesFactoryBean.getObject();

}

@Bean

public JobDetailFactoryBean job1() {

JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();

jobDetailFactoryBean.setJobClass(QuartzJob.class);

jobDetailFactoryBean.setDurability(true);

jobDetailFactoryBean.setRequestsRecovery(true);

return jobDetailFactoryBean;

}

@Bean

public CronTriggerFactoryBean trigger1() {

CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();

cronTriggerFactoryBean.setJobDetail(job1().getObject());

cronTriggerFactoryBean.setCronExpression("0/3 * * * * ?");

return cronTriggerFactoryBean;

}

@Bean

public Executor schedulerThreadPool() {

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

executor.setCorePoolSize(15);

executor.setMaxPoolSize(25);

executor.setQueueCapacity(100);

return executor;

}

}

Quartz job类

package test.daemon.clusterquartz.quartz;

import java.util.Date;

import org.quartz.DisallowConcurrentExecution;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.quartz.PersistJobDataAfterExecution;

import org.springframework.scheduling.quartz.QuartzJobBean;

@PersistJobDataAfterExecution

@DisallowConcurrentExecution

public class QuartzJob extends QuartzJobBean {

@Override

protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

// TODO Auto-generated method stub

System.out.println("\nQuartz job " + new Date());

}

}

Spring Boot启动类

package test.daemon.clusterquartz;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class Cluster {

public static void main(String[] args) throws Exception {

SpringApplication.run(Cluster.class, args);

}

}

数据库sql

可以在Quartz的lib中找到适当的数据库生成文件来创建jdbc job store所需要的表。这些表用于Quartz在集群环境中的调度。

一些解释

把项目复制一份,然后改掉spring server的启动端口,启动多个项目,可以观察到只有一个项目的Quartz在运行。如果当前运行Quartz的服务器挂掉,另一台会跟进执行相同的Quartz任务。

有待思考的部分

在Quartz集群环境中,时间的同步是一个重要问题,有时间需要去看一下怎么进行时间同步来确保集群的正确性。

总结

以上是 SpringBoot与Quartz集成实现分布式定时任务集群的代码实例 的全部内容, 来源链接: utcz.com/z/323896.html

回到顶部