完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群

maven依赖

<dependency>

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

<artifactId>quartz</artifactId>

<version>2.2.1</version>

</dependency>

<dependency>

<groupId>open-source.missing.com.oracle</groupId>

<artifactId>ojdbc6</artifactId>

<version>11.2.0.3.0</version>

</dependency>

<dependency>

<groupId>commons-dbcp</groupId>

<artifactId>commons-dbcp</artifactId>

<version>1.4</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

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

<version>3.2.16.RELEASE</version>

</dependency>

执行从官网下载的gz文件中的sql语句(http://www.quartz-scheduler.org/),注意使用的jar版本和sql脚本必须保持一致。不然会出现各种奇葩问题。比如启动程序后,定时任务不执行。

quartz.properties配置

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.dataSource = myDS

org.quartz.jobStore.isClustered=true

org.quartz.jobStore.clusterCheckinInterval = 60000   //集群模式下检测节点失败的轮询间隔,默认15秒。如果定时间隔为10秒,检测间隔为60秒,如果从节点失败到检测到过去了45秒,则检测到那一刻,会同时触发5个实例,这里一定要注意。

# org.quartz.plugins.history.LoggingJobHistoryPlugin

# org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin

# org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger \{1\}.\{0\} fired job \{6\}.\{5\} at: \{4, date, HH:mm:ss MM/dd/yyyy}

# org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger \{1\}.\{0\} completed firing job \{6\}.\{5\} at \{4, date, HH:mm:ss MM/dd/yyyy\}.

org.quartz.scheduler.instanceName = MyClusteredScheduler

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

org.quartz.threadPool.threadCount = 5

org.quartz.threadPool.threadPriority = 5

org.quartz.scheduler.instanceId=AUTO

org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin

org.quartz.plugin.shutdownhook.cleanShutdown = true

org.quartz.dataSource.myDS.driver = oracle.jdbc.OracleDriver

org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@172.23.11.49:1522:fcdb

org.quartz.dataSource.myDS.user = hs_fund

org.quartz.dataSource.myDS.password = Hundsun123

org.quartz.dataSource.myDS.maxConnections = 5

org.quartz.dataSource.myDS.validationQuery=select 1 from dual

org.quartz.dataSource.myDS.validateOnCheckout=true

spring配置文件

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

<property name="username" value="hs_fund"></property>

<property name="password" value="Hundsun123"></property>

<property name="url" value="jdbc:oracle:thin:@172.23.11.49:1522:fcdb"></property>

<property name="driverClassName" value="oracle.jdbc.OracleDriver"></property>

<property name="maxActive" value="10"></property>

<property name="maxIdle" value="10"></property>

<property name="minIdle" value="10"></property>

<property name="maxWait" value="10000"></property>

<property name="poolPreparedStatements" value="true" />

<property name="maxOpenPreparedStatements" value="50" />

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<property name="dataSource">

<ref bean="dataSource"/>

</property>

<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>

<!--applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文-->

<property name="triggers">

<list>

<ref bean="cronTrigger"/>

<!-- <ref bean="simpleTrigger"/> -->

</list>

</property>

<property name="configLocation" value="classpath:quartz.properties"/>

<!--configLocation:用于指明quartz的配置文件的位置 -->

</bean>

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

<property name="jobDetail" ref="exampleJob"/>

<!-- run every morning at 6 AM -->

<property name="cronExpression" value="*/10 * * * * ?"/>

</bean>

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

<property name="jobClass" value="examples.ExampleJob"/>

<property name="durability" value="true" />

<property name="requestsRecovery" value="true" />

<property name="jobDataAsMap">

<map>

<entry key="timeout" value="5"/>

</map>

</property>

</bean>

examples.ExampleJob

/**

* @Title: ExampleJob.java

* @Package example

* @Description: TODO(用一句话描述该文件做什么)

* @author [email protected]

* @date 2016年3月11日 上午11:48:28

* @version V1.0

*/

package examples;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

/**

* @author zjhua

*

*/

public class ExampleJob extends QuartzJobBean {

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");

private int timeout;

/**

* Setter called after the ExampleJob is instantiated

* with the value from the JobDetailFactoryBean (5)

*/

public void setTimeout(int timeout) {  //会自动从bean配置中注入

this.timeout = timeout;

}

protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {

String dt = sdf.format(new Date());

System.out.println(ctx.getJobDetail().getJobDataMap().get("timeout"));  //会自动从bean配置中设置进来

System.out.println(dt + "ExampleJob===========");

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(dt + "ExampleJob定时任务结束");

}

}

//测试类

/**

* @Title: SpringTest.java

* @Package com.cyl

* @Description: TODO(用一句话描述该文件做什么)

* @author [email protected]

* @date 2016年3月10日 上午9:12:27

* @version V1.0

*/

package com.cyl;

import javax.sql.DataSource;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.SchedulerException;

import org.quartz.impl.StdSchedulerFactory;

import org.quartz.impl.matchers.GroupMatcher;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**

* @author zjhua

*

*/

public class SpringTest {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext(

new String[] { "services.xml" });

/*

TaskExecutorExample taskExecutor = context

.getBean(com.cyl.TaskExecutorExample.class);

taskExecutor.printMessages();

DataSource dataSource = context.getBean(DataSource.class);

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

long begin = System.currentTimeMillis();

for (int i=0;i<2000;i++) {

int countOfActorsNamedJoe = jdbcTemplate.queryForObject("select count(*) from t1 where a = ?",Integer.class,new String[] {"1"});

System.out.print(countOfActorsNamedJoe);

}

System.out.println("");

long end = System.currentTimeMillis();

System.out.println(end-begin);

*/

SchedulerFactoryBean bean = context.getBean(SchedulerFactoryBean.class);

try {

//Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

//System.out.println(scheduler.getSchedulerName());

System.out.println(bean.getScheduler().getSchedulerName());

for(String group : bean.getScheduler().getJobGroupNames()) {

GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(group);

for(JobKey jobKey : bean.getScheduler().getJobKeys(groupMatcher)) {

System.out.println("Found job identified by: " + jobKey);

}

}

try {

//Thread.sleep(60);

//System.out.println("定时任务暂停");

//bean.getScheduler().pauseAll();  //可以scheduler级别、触发器级别、任务级别,可以查询状态等各种信息

Thread.sleep(60);

//bean.getScheduler().resumeAll();

//System.out.println("定时任务重新开启");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//Thread.sleep(20000);

//scheduler.shutdown();

//System.out.println(scheduler.getSchedulerName() + "已关闭!");

} catch (SchedulerException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

其他需要注意的点:更改了quartz.properties或者spring配置文件,重启时,现有数据库中的quartz任务定义不会被更新,如果希望更新它们的话,需要通过quartz API进行更新,或者重建quartz表并重启应用。

其他定时任务以及触发器操作

调度器暂停

bean.getScheduler().pauseAll();

删除触发器

bean.getScheduler().unscheduleJob(new TriggerKey("cronTrigger","DEFAULT"));

删除任务

bean.getScheduler().deleteJob(new JobKey("exampleJob","DEFAULT"));

创建任务

JobDataMap jobDataMap = new JobDataMap();

jobDataMap.put("timeout", 5);

JobDetail jd = JobBuilder.newJob(examples.ExampleJob.class)

.setJobData(jobDataMap).withIdentity(new JobKey("exampleJob","DEFAULT")).requestRecovery(true).storeDurably(true).build();

创建触发器

CronTriggerImpl trigger = new CronTriggerImpl();

try {

trigger.setCronExpression("*/20 * * * * ?");

trigger.setKey(new TriggerKey("cronTrigger","DEFAULT"));

开始调度触发器

bean.getScheduler().scheduleJob(jd,trigger);

知道上述API之后,就可以在spring的配置文件中不包含任何的trigger以及jobdetail定义,而是根据数据库中的配置进行动态管理(当然,我们也是采用这种方法)。

时间: 2024-10-03 01:58:59

完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群的相关文章

Python Django 集成Redis Sentinel(哨兵)集群开发秒杀系统

我们知道秒杀系统最大特点是瞬时高并发.高访问量的系统.我们还要保证它的高可用性.这里我们采用Python Django 集成Redis Sentinel(哨兵)集群开发秒杀系统. Redis Sentinel(哨兵)集群Redis哨兵为Redis集群提供了高可用性.实际上这意味着我们可以使用哨兵模式创建一个可以不用人为干预而应对各种故障的Redis集群部署.可大大提高系统的高可用性. 哨兵模式还提供了其他的附加功能,如监控,通知,为客户端提供配置. 下面是在宏观层面上哨兵模式的功能列表: 监控:

spring cloud 搭建注册中心Eureka(集群模式)

集群 注册中心这么关键的服务,如果是单点话,遇到故障就是毁灭性的.在一个分布式系统中,服务注册中心是最重要的基础部分,理应随时处于可以提供服务的状态.为了维持其可用性,使用集群是很好的解决方案.Eureka通过互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用的serviceUrl就能实现高可用部署. 新建3个配置文件 application-peer1.yml spring: application: name: Service #应用名称,也是服务注册的

Quartz cron 表达式(linux 定时器,java 定时任务,spring task定时任务)

Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但还是有少许明显的区别.区别之一就是 Quartz 的格式向下支持到秒级别的计划,而 UNIX cron 计划仅支持至分钟级.许多我们的触发计划要基于秒级递增的(例如,每45秒),因此这是一个非常好的差异. 在 UNIX cron 里,要执行的作业(或者说命令)是存放在 cron 表达式中的,在第六个域位置上.Quartz 用 cron 表达式存放执行计划.引用了 cron 表达式的 CronTrigger 在计划的时间里

Gitlab CI 集成 Kubernetes 集群部署 Spring Boot 项目

在上一篇博客中,我们成功将 Gitlab CI 部署到了 Docker 中去,成功创建了 Gitlab CI Pipline 来执行 CI/CD 任务.那么这篇文章我们更进一步,将它集成到 K8s 集群中去.这个才是我们最终的目标.众所周知,k8s 是目前最火的容器编排项目,很多公司都使用它来构建和管理自己容器集群,可以用来做机器学习训练以及 DevOps 等一系列的事情. 在这里,我们聚焦 CI/CD,针对于 Spring Boot 项目,借助 Gitlab CI 完成流水线的任务配置,最终部

Spring集成Quartz的3种方式

1.使用xml配置方式 Maven依赖 <properties> <!-- spring版本号 --> <spring.version>4.2.2.RELEASE</spring.version> <!-- Quartz的版本 --> </properties> <dependency> <groupId>org.springframework</groupId> <artifactId>

分布式架构中一致性解决方案——Zookeeper集群搭建

当我们的项目在不知不觉中做大了之后,各种问题就出来了,真jb头疼,比如性能,业务系统的并行计算的一致性协调问题,比如分布式架构的事务问题, 我们需要多台机器共同commit事务,经典的案例当然是银行转账,支付宝转账这种,如果是一台机器的话,这个还是很方便的,windows中自带了一个事务协 调器mstsc,但是呢,你那种很大很牛逼的项目不可能全是windows服务器,对吧,有些人为了解决这个问题,会采用2pc,3pc这种算法,或者是paxos的思 想进行分布式下的一致性处理,当然在这个世界上,真

主流MPP解决方案Postgres-XL集群修炼之路视频课程

课程分享:https://pan.baidu.com/s/1PcbHmi5z74ix8WqE7Nde1w 提取码: 4iqt 本课程采用最新稳定版本Postgres-XL v9.5,是当今应用覆盖面最广的MPP解决方案. Postgres-XL是开源的postgresql集群,是由多个独立的PostgreSQL实例组成,它们分布在不同的物理(或虚拟)主机上协同工作,呈现给用户的是一个数据库实例的效果. 曾经风靡一时的MPP解决方案Greenplum是基于postgres-xl的8.2版本封装的,

spring boot 整合 quartz 集群环境 实现 动态定时任务配置【原】

最近做了一个spring boot 整合 quartz  实现 动态定时任务配置,在集群环境下运行的 任务.能够对定时任务,动态的进行增删改查,界面效果图如下: 1. 在项目中引入jar 2. 将需要的表导入数据库 官网上有不同数据库的脚本,找到对应的,导入即可 3. java 代码 将quartz 的相关配置文件,配置为暴露bean,方便后期引用. 有一处关键的地方,就是注入spring 上下文,也可以算是一个坑.如果,不注入spring 上下文,那么新添加的定时任务job,是新new 的一个

Spring+quartz 实现定时任务job集群配置

为什么要有集群定时任务? 因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真实结果的3倍,那对银行来说是无法想象的,完全不可接受. 集群定时任务工作原理 所以为了解决以上问题,每个server把将要及正在运行的job所有状态都即时同步到中央数据库,然后再次触发调用时从数据库中分析是否已有别的server正在运行相同job (同名同定时时间点的job属于相当job),如果相同