Quartz Spring分布式集群搭建Demo

Posted dzpykj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz Spring分布式集群搭建Demo相关的知识,希望对你有一定的参考价值。

注:关于单节点的Quartz使用在这里不做详细介绍,直接进阶为分布式集群版的

1.准备工作:

使用环境Spring4.3.5,Quartz2.2.3,持久化框架JDBCTemplate

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>com.dzpykj</groupId>
	<artifactId>quartz-test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.3.5.RELEASE</spring.version>
	</properties>

	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.3</version>
		</dependency>

		<!-- servlet 3 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
		</dependency>

		<!-- Spring dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
		<dependency>
			<groupId>commons-pool</groupId>
			<artifactId>commons-pool</artifactId>
			<version>1.6</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>


		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.3.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.3.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.7</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<!-- 打War 的一个插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.6</version>
			</plugin>
			<!-- 编译插件 -->
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
		<finalName>qt</finalName>
	</build>

</project>

2.数据库建表:11张

官网下载2.2.3地址:http://www.quartz-scheduler.org/downloads/

下载完后将下图的SQL文件中的语句拿到数据库执行

技术分享图片

3.将该数据库配置到Quartz的配置文件quartz.properties中

org.quartz.scheduler.instanceName = TestScheduler1   
org.quartz.scheduler.instanceId = AUTO  

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.dataSource = myDS 
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered = true  
org.quartz.jobStore.clusterCheckinInterval = 10000


org.quartz.dataSource.myDS.driver =com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL =jdbc\\:mysql\\://127.0.0.1\\:3306/quartz_test?useUnicode\\=true&characterEncoding\\=utf8&autoReconnect\\=true
org.quartz.dataSource.myDS.user =root
org.quartz.dataSource.myDS.password =root    
org.quartz.dataSource.myDS.maxConnections = 5

4.配置applicationContext-quartz.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

    <!-- Quartz集群Schduler -->
    <bean id="clusterQuartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- Triggers集成   动态配置 -->
        <!-- <property name="triggers">
            <list>
                <ref bean="allocationPlanTrigger" />
            </list>
        </property> -->
        <!-- quartz配置文件路径, 指向cluster配置 -->
        <property name="configLocation" value="classpath:quartz.properties" />
        <!-- 启动时延期0秒开始任务 -->
        <property name="startupDelay" value="0" />
        <!-- 保存Job数据到数据库所需的数据源 -->
        <!-- <property name="dataSource" ref="dataSource" /> -->
        <!-- Job接受applicationContext的成员变量名 -->
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />
        <!-- 修改job时,更新到数据库 -->
        <property name="overwriteExistingJobs" value="true" />
    </bean>

</beans>

 

5.建工具类

package com.dzpykj.plugins.quartz.dynamic;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

public class QuartzTaskUtils {

    public static String addTask(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
            String cronExp, Class jobClass, JdbcTemplate jdbcTemplate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();

            JobDetail jobDetail = newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            CronTrigger simpleTrigger = newTrigger().withIdentity(triggerName, triggerGroupName)
                    .withSchedule(cronSchedule(cronExp)).startNow().build();
            Date ft = scheduler.scheduleJob(jobDetail, simpleTrigger);
            scheduler.start();
            System.err.println("定时任务开始执行");
        } catch (ObjectAlreadyExistsException e) {
            e.printStackTrace();
            return "相同组内有重名的工作名称或者触发器名称";
        } catch (SchedulerException e) {
            e.printStackTrace();
            return "保存定时任务异常";
        }
        return "success";
    }

    public static String removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
            JdbcTemplate jdbcTemplate) {
        try {
            String jobSql = "select * from qrtz_triggers where JOB_NAME = ? and JOB_GROUP = ?";
            List jobList = jdbcTemplate.queryForList(jobSql, jobName, jobGroupName);
            if (jobList.size() < 1) {
                return "数据库没有该任务";
            }
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);// 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            JobKey jobKey = new JobKey(jobName, jobGroupName);
            scheduler.deleteJob(jobKey);// 删除任务
        } catch (SchedulerException e) {
            e.printStackTrace();
            return "fail";
        }
        return "success";
    }

}

 

测试可能会用到的URL

测试Quartz分布式集群,分别两个端口启动Tomcat,各访访问一次,看控制台,在看数据库表,慢慢研究,可定会有收获

新增任务URL http:
//127.0.0.1:8080/addTask?jobName=UserVisitCountJob1&jobGroupName=UserVisitCountJobGroup1&triggerName=simpleTrigger1&triggerGroupName=triggerGroup1 删除任务URL http://127.0.0.1:8080/removeTask?jobName=UserVisitCountJob1&jobGroupName=UserVisitCountJobGroup1&triggerName=simpleTrigger1&triggerGroupName=triggerGroup1

 

 

 以上只是将一些关键步骤说明

代码的GitHub地址,供大家下载完整代码  https://github.com/PinBo1991/qt

 编写代码过程中参考的大神资料:https://www.cnblogs.com/jiafuwei/p/6145280.htmlhttps://www.cnblogs.com/kingpeng/p/7137384.html,供大家加以理解

 

关于quartz.properties配置详解如下

#Configure Main Scheduler Properties    
#==============================================================
#配置集群时,quartz调度器的id,由于配置集群时,只有一个调度器,必须保证每个服务器该值都相同,可以不用修改,只要每个ams都一样就行  
org.quartz.scheduler.instanceName = Scheduler1      
#集群中每台服务器自己的id,AUTO表示自动生成,无需修改  
org.quartz.scheduler.instanceId = AUTO    
#==============================================================    
#Configure ThreadPool    
#==============================================================  
#quartz线程池的实现类,无需修改     
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool   
#quartz线程池中线程数,可根据任务数量和负责度来调整    
org.quartz.threadPool.threadCount = 5     
#quartz线程优先级  
org.quartz.threadPool.threadPriority = 5    
#==============================================================    
#Configure JobStore    
#==============================================================     
#表示如果某个任务到达执行时间,而此时线程池中没有可用线程时,任务等待的最大时间,如果等待时间超过下面配置的值(毫秒),本次就不在执行,而等待下一次执行时间的到来,可根据任务量和负责程度来调整  
org.quartz.jobStore.misfireThreshold = 60000     
#实现集群时,任务的存储实现方式,org.quartz.impl.jdbcjobstore.JobStoreTX表示数据库存储,无需修改  
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX    
#quartz存储任务相关数据的表的前缀,无需修改   
org.quartz.jobStore.tablePrefix = QRTZ_   
#连接数据库数据源名称,与下面配置中org.quartz.dataSource.myDS的myDS一致即可,可以无需修改    
org.quartz.jobStore.dataSource = myDS  
#是否启用集群,启用,改为true,注意:启用集群后,必须配置下面的数据源,否则quartz调度器会初始化失败     
org.quartz.jobStore.isClustered = false    
#集群中服务器相互检测间隔,每台服务器都会按照下面配置的时间间隔往服务器中更新自己的状态,如果某台服务器超过以下时间没有checkin,调度器就会认为该台服务器已经down掉,不会再分配任务给该台服务器  
org.quartz.jobStore.clusterCheckinInterval = 20000    
#==============================================================    
#Non-Managed Configure Datasource    
#==============================================================  
#配置连接数据库的实现类,可以参照IAM数据库配置文件中的配置     
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver    
#配置连接数据库连接,可以参照IAM数据库配置文件中的配置    
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/test   
#配置连接数据库用户名  
org.quartz.dataSource.myDS.user = yunxi  
#配置连接数据库密码  
org.quartz.dataSource.myDS.password = 123456  
#配置连接数据库连接池大小,一般为上面配置的线程池的2倍  
org.quartz.dataSource.myDS.maxConnections = 10   

 



以上是关于Quartz Spring分布式集群搭建Demo的主要内容,如果未能解决你的问题,请参考以下文章

Spring+Quartz框架实现定时任务(集群,分布式)

Spring整合Quartz定时任务 在集群分布式系统中的应用(Mysql数据库环境)

Quartz实战源码解析Quartz分布式集群实现

Quartz实战源码解析Quartz分布式集群实现

Quartz实战源码解析Quartz分布式集群实现

spring quartz定时任务集群环境下如何实现只在单个节点运行