1. 程式人生 > >Quartz Spring分布式集群搭建Demo

Quartz Spring分布式集群搭建Demo

必須 庫存 連接數據庫 線程 vax etx ESS gets 開始

註:關於單節點的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.html和https://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