[java]spring-Quartz集群

来源:互联网 发布:淘宝古玩店 编辑:程序博客网 时间:2024/05/23 20:31

上篇博客讲了quartz的用法,解决了定时任务的问题,但是当我们搭建集群,将服务部署在多个机器上时,很有可能引起冲突的问题,一个任务,多次执行,那么如何解决这个问题呢,quartz提供了集群的搭建方案,确保一个任务,只会在一个时间执行一次,下面我们来学习一下quartz集群的搭建。

原理

quartz连接数据库,然后从表里去读取相关配置信息,多个任务通过表来达到统一。

搭建

环境

spring 4.0.6
quartz 2.2.3
mysql 5.1.38
druid 1.1.0
首先来看一下目录结构:
这里写图片描述

pom文件引用如下:

<?xml version="1.0" encoding="UTF-8"?><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.spring.quartzm</groupId>    <artifactId>quartzm</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <springframework.version>4.0.6.RELEASE</springframework.version>        <quartz.version>2.2.3</quartz.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-core</artifactId>            <version>${springframework.version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context-support</artifactId>            <version>${springframework.version}</version>        </dependency>        <!-- spring-tx包必须导入,因为Quartz需要依赖该包 -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-tx</artifactId>            <version>${springframework.version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-web</artifactId>            <version>${springframework.version}</version>        </dependency>        <!-- Quartz framework -->        <dependency>            <groupId>org.quartz-scheduler</groupId>            <artifactId>quartz</artifactId>            <version>${quartz.version}</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-jdbc</artifactId>            <version>4.3.3.RELEASE</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>5.1.38</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.1.0</version>        </dependency>    </dependencies></project>

数据库连接

数据库的建表语句等在quartz-2.2.3-distribution.tar.gz包里面quartz-2.2.3-distribution.tar\quartz-2.2.3\docs\dbTables\下,因为我的数据库是mysql,所以我选择的是tables_mysql_innodb.sql

spring我只用了一个配置文件,名字为quartz-context.xml,数据库建好以后,配置数据库连接,如下:

  <!--数据库连接设置-->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">        <property name="url" value="${itoo_jdbc_url}"/>        <property name="username" value="${itoo_jdbc_username}"/>        <property name="password" value="${itoo_jdbc_password}"/>    </bean>    <!--<import resource="classpath:quartz-db.properties"/>-->    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <property name="order" value="1" />        <property name="ignoreUnresolvablePlaceholders" value="true" />        <property name="locations">            <list>                <value>classpath:db.properties</value>                <!--<value>classpath:dubbo-server.properties</value>-->            </list>        </property>    </bean>

quartz配置文件

配置文件内容为:

#==============================================================#Configure Main Scheduler Properties#==============================================================org.quartz.scheduler.instanceName = defaultScheduler  org.quartz.scheduler.instanceId = AUTO  #==============================================================#Configure JobStore#==============================================================org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate  org.quartz.jobStore.tablePrefix = QRTZ_  org.quartz.jobStore.isClustered = true  org.quartz.jobStore.clusterCheckinInterval = 20000    org.quartz.jobStore.dataSource = myDS  org.quartz.jobStore.maxMisfiresToHandleAtATime = 1  org.quartz.jobStore.misfireThreshold = 120000  org.quartz.jobStore.txIsolationLevelSerializable = true  #==============================================================#Configure ThreadPool#==============================================================org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  org.quartz.threadPool.threadCount = 10  org.quartz.threadPool.threadPriority = 5  org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true  #==============================================================#Skip Check Update#update:true#not update:false#==============================================================org.quartz.scheduler.skipUpdateCheck = true   #============================================================================# Configure Plugins#============================================================================org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin     org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin  org.quartz.plugin.shutdownhook.cleanShutdown = true  

spring配置文件内容

JobDetail配置

上篇博客中我们配置jobDetail时使用的是org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
但是在搭建集群时使用这个会报错,说我们的任务类没有序列化,所以我们使用另一种
org.springframework.scheduling.quartz.JobDetailFactoryBean
如下:

    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">        <property name="jobClass" value="com.cdsmartlink.service.impl.ExtendsJob"/>        <property name="durability" value="true"/>        <property name="requestsRecovery" value="true"/>    </bean>

Trigger与上一篇相同即可

<!-- 创建SimpleTrigger触发器 -->    <bean class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean" id="simpleTrigger">        <!-- 引用任务 -->        <property name="jobDetail" ref="jobDetail"/>        <!-- 指定循环时间,以秒为单位 -->        <property name="repeatInterval" value="10000"/>    </bean>    <!-- 创建CronTrigger触发器 -->    <bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean" id="cronTrigger">        <!-- 引用任务 -->        <property name="jobDetail" ref="jobDetail"/>        <!-- 指定Cron表达式 -->        <property name="cronExpression" value="*/5 * * * * ?"/>    </bean>

Scheduling需要注意一下

<!-- 创建调度器 -->    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" id="stdScheduler">        <property name="dataSource" ref="dataSource"></property>        <!--可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->        <property name="overwriteExistingJobs" value="true" />        <!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->        <property name="startupDelay" value="30" />        <!-- 设置自动启动 -->        <property name="autoStartup" value="true" />        <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />        <property name="configLocation" value="classpath:quartz.properties" />        <property name="triggers">            <list>                <ref bean="cronTrigger"/>        </list>    </property></bean>

完整的quartz-context.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:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">    <context:component-scan base-package="com.cdsmartlink.*" />    <!--&lt;!&ndash; 创建任务 &ndash;&gt;-->    <!--<bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" id="jobDetail">-->        <!--&lt;!&ndash; 目标对象 &ndash;&gt;-->        <!--<property name="targetObject" ref="myJob"/>-->        <!--&lt;!&ndash; 目标方法 &ndash;&gt;-->        <!--<property name="targetMethod" value="execute"/>-->        <!--&lt;!&ndash;concurrent:false表示上一个任务执行完后再开启新的任务&ndash;&gt;-->        <!--<property name="concurrent" value="false"/>-->    <!--</bean>-->    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">        <property name="jobClass" value="com.cdsmartlink.service.impl.ExtendsJob"/>        <property name="durability" value="true"/>        <property name="requestsRecovery" value="true"/>    </bean>    <!-- 创建SimpleTrigger触发器 -->    <bean class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean" id="simpleTrigger">        <!-- 引用任务 -->        <property name="jobDetail" ref="jobDetail"/>        <!-- 指定循环时间,以秒为单位 -->        <property name="repeatInterval" value="10000"/>    </bean>    <!-- 创建CronTrigger触发器 -->    <bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean" id="cronTrigger">        <!-- 引用任务 -->        <property name="jobDetail" ref="jobDetail"/>        <!-- 指定Cron表达式 -->        <property name="cronExpression" value="*/5 * * * * ?"/>    </bean>    <!-- 创建调度器 -->    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" id="stdScheduler">        <property name="dataSource" ref="dataSource"></property>        <!--可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->        <property name="overwriteExistingJobs" value="true" />        <!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->        <property name="startupDelay" value="30" />        <!-- 设置自动启动 -->        <property name="autoStartup" value="true" />        <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />        <property name="configLocation" value="classpath:quartz.properties" />        <property name="triggers">            <list>                <ref bean="cronTrigger"/>            </list>        </property>    </bean>    <!--数据库连接设置-->    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">        <property name="url" value="${itoo_jdbc_url}"/>        <property name="username" value="${itoo_jdbc_username}"/>        <property name="password" value="${itoo_jdbc_password}"/>    </bean>    <!--<import resource="classpath:quartz-db.properties"/>-->    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <property name="order" value="1" />        <property name="ignoreUnresolvablePlaceholders" value="true" />        <property name="locations">            <list>                <value>classpath:db.properties</value>                <!--<value>classpath:dubbo-server.properties</value>-->            </list>        </property>    </bean></beans>

任务类

任务类需要实现Job接口

package com.cdsmartlink.service;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.stereotype.Component;/** * Created by L on 2017-07-22. */@Componentpublic class ExtendsJob implements Job{    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {        System.out.println("这里是我们的任务代码!!!!");    }}

测试

package com.cdsmartlink.service.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * Created by L on 2017-07-22. */public class MyJobTest{    @Test    public void test() throws InterruptedException {        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("quartz-context.xml");        Thread.sleep(60000);    }}

其实也可以在tomcat上多发布几个,来进行测试,这里就不举例子了。

总结

一开始研究Quartz集群的时候,其实我是很无语的,毕竟感觉这个用处不是很大,不过研究着就会发现,有很多比自己牛多了的人,在全心全意为人民服务。

原创粉丝点击