关键词:
集群环境可能出现的问题
在上一篇博客我们介绍了如何在自己的项目中从无到有的添加了Quartz定时调度引擎,其实就是一个Quartz 和Spring的整合过程,很容易实现,但是我们现在企业中项目通常都是部署在集群环境中的,这样我们之前的定时调度就会出现问题了,因为我们的定时任务都加载在内存中的,每个集群节点中的调度器都会去执行,这就会存在重复执行和资源竞争的问题,那么如何来解决这样的问题呢,往下面看吧...
解决方案
在一般的企业中解决类似的问题一般都是在一个note上部署Quartz其他note不部署(或者是在其他几个机器加IP地址过滤),但是这样集群对于定时任务来说就没有什么意义了,而且存在着单点故障的隐患,也就是这台部署着Quartz的机器一旦挂了,我们的定时任务就停止服务了,这绝对不是我们想要的。
Quartz本身是支持集群的,我们通过Quartz的集群方式来解决这样的问题。
Quartz集群
虽然单个 Quartz 实例能给予你很好的 Job调度能力,但它不能令典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的 Job,Quartz 集群势必成为你方言的一部分了,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。 QuartzJob Scheduling Framework
了解了Quartz集群的好处,接下来就对我们之前的工程进行改造,增加Quartz集群特性。
Quartz集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群
所以我们集群的第一步就是建立Quartz所需要的12张表:
1、建表
在quartz核心包里面通过quartz提供的建表语句建立相关表结构
生成的表结构如下
这几张表是用于存储任务信息,触发器,调度器,集群节点等信息
详细解释:
QRTZ_CRON_TRIGGERS 存储Cron Trigger,包括Cron 表达式和时区信息
QRTZ_PAUSED_TRIGGER_GRPS 存储已暂停的Trigger 组的信息
QRTZ_LOCKS 存储程序的非观锁的信息(假如使用了悲观锁)
QRTZ_JOB_LISTENERS 存储有关已配置的JobListener 的信息
QRTZ_BLOG_TRIGGERS Trigger 作为Blob 类型存储(用于Quartz 用户用JDBC 创建他们自己定制的Trigger 类型,JobStore并不知道如何存储实例的时候)
QRTZ_TRIGGERS 存储已配置的Trigger 的信息
所有的表默认以前缀QRTZ_开始。可以通过在quartz.properties配置修改(org.quartz.jobStore.tablePrefix= QRTZ_)。
共12张表的SQL脚本
1 # # Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar # # In your Quartz properties file, you'll need to set 2 # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate 3 # 4 5 DROP TABLE IF EXISTS QRTZ_JOB_LISTENERS; DROP TABLE IF EXISTS QRTZ_TRIGGER_LISTENERS; DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; DROP TABLE IF EXISTS QRTZ_LOCKS; DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; DROP TABLE IF EXISTS QRTZ_TRIGGERS; DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; DROP TABLE IF EXISTS QRTZ_CALENDARS; CREATE TABLE QRTZ_JOB_DETAILS 6 ( 7 JOB_NAME VARCHAR(200) NOT NULL, 8 JOB_GROUP VARCHAR(200) NOT NULL, 9 DESCRIPTION VARCHAR(250) NULL, 10 JOB_CLASS_NAME VARCHAR(250) NOT NULL, 11 IS_DURABLE VARCHAR(1) NOT NULL, 12 IS_VOLATILE VARCHAR(1) NOT NULL, 13 IS_STATEFUL VARCHAR(1) NOT NULL, 14 REQUESTS_RECOVERY VARCHAR(1) NOT NULL, 15 JOB_DATA BLOB NULL, 16 PRIMARY KEY (JOB_NAME,JOB_GROUP) 17 ); CREATE TABLE QRTZ_JOB_LISTENERS 18 ( 19 JOB_NAME VARCHAR(200) NOT NULL, 20 JOB_GROUP VARCHAR(200) NOT NULL, 21 JOB_LISTENER VARCHAR(200) NOT NULL, 22 PRIMARY KEY (JOB_NAME,JOB_GROUP,JOB_LISTENER), 23 FOREIGN KEY (JOB_NAME,JOB_GROUP) 24 REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP) 25 ); CREATE TABLE QRTZ_TRIGGERS 26 ( 27 TRIGGER_NAME VARCHAR(200) NOT NULL, 28 TRIGGER_GROUP VARCHAR(200) NOT NULL, 29 JOB_NAME VARCHAR(200) NOT NULL, 30 JOB_GROUP VARCHAR(200) NOT NULL, 31 IS_VOLATILE VARCHAR(1) NOT NULL, 32 DESCRIPTION VARCHAR(250) NULL, 33 NEXT_FIRE_TIME BIGINT(13) NULL, 34 PREV_FIRE_TIME BIGINT(13) NULL, 35 PRIORITY INTEGER NULL, 36 TRIGGER_STATE VARCHAR(16) NOT NULL, 37 TRIGGER_TYPE VARCHAR(8) NOT NULL, 38 START_TIME BIGINT(13) NOT NULL, 39 END_TIME BIGINT(13) NULL, 40 CALENDAR_NAME VARCHAR(200) NULL, 41 MISFIRE_INSTR SMALLINT(2) NULL, 42 JOB_DATA BLOB NULL, 43 PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP), 44 FOREIGN KEY (JOB_NAME,JOB_GROUP) 45 REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP) 46 ); CREATE TABLE QRTZ_SIMPLE_TRIGGERS 47 ( 48 TRIGGER_NAME VARCHAR(200) NOT NULL, 49 TRIGGER_GROUP VARCHAR(200) NOT NULL, 50 REPEAT_COUNT BIGINT(7) NOT NULL, 51 REPEAT_INTERVAL BIGINT(12) NOT NULL, 52 TIMES_TRIGGERED BIGINT(10) NOT NULL, 53 PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP), 54 FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 55 REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP) 56 ); CREATE TABLE QRTZ_CRON_TRIGGERS 57 ( 58 TRIGGER_NAME VARCHAR(200) NOT NULL, 59 TRIGGER_GROUP VARCHAR(200) NOT NULL, 60 CRON_EXPRESSION VARCHAR(200) NOT NULL, 61 TIME_ZONE_ID VARCHAR(80), 62 PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP), 63 FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 64 REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP) 65 ); CREATE TABLE QRTZ_BLOB_TRIGGERS 66 ( 67 TRIGGER_NAME VARCHAR(200) NOT NULL, 68 TRIGGER_GROUP VARCHAR(200) NOT NULL, 69 BLOB_DATA BLOB NULL, 70 PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP), 71 FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 72 REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP) 73 ); CREATE TABLE QRTZ_TRIGGER_LISTENERS 74 ( 75 TRIGGER_NAME VARCHAR(200) NOT NULL, 76 TRIGGER_GROUP VARCHAR(200) NOT NULL, 77 TRIGGER_LISTENER VARCHAR(200) NOT NULL, 78 PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_LISTENER), 79 FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP) 80 REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP) 81 ); CREATE TABLE QRTZ_CALENDARS 82 ( 83 CALENDAR_NAME VARCHAR(200) NOT NULL, 84 CALENDAR BLOB NOT NULL, 85 PRIMARY KEY (CALENDAR_NAME) 86 ); CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS 87 ( 88 TRIGGER_GROUP VARCHAR(200) NOT NULL, 89 PRIMARY KEY (TRIGGER_GROUP) 90 ); CREATE TABLE QRTZ_FIRED_TRIGGERS 91 ( 92 ENTRY_ID VARCHAR(95) NOT NULL, 93 TRIGGER_NAME VARCHAR(200) NOT NULL, 94 TRIGGER_GROUP VARCHAR(200) NOT NULL, 95 IS_VOLATILE VARCHAR(1) NOT NULL, 96 INSTANCE_NAME VARCHAR(200) NOT NULL, 97 FIRED_TIME BIGINT(13) NOT NULL, 98 PRIORITY INTEGER NOT NULL, 99 STATE VARCHAR(16) NOT NULL, 100 JOB_NAME VARCHAR(200) NULL, 101 JOB_GROUP VARCHAR(200) NULL, 102 IS_STATEFUL VARCHAR(1) NULL, 103 REQUESTS_RECOVERY VARCHAR(1) NULL, 104 PRIMARY KEY (ENTRY_ID) 105 ); CREATE TABLE QRTZ_SCHEDULER_STATE 106 ( 107 INSTANCE_NAME VARCHAR(200) NOT NULL, 108 LAST_CHECKIN_TIME BIGINT(13) NOT NULL, 109 CHECKIN_INTERVAL BIGINT(13) NOT NULL, 110 PRIMARY KEY (INSTANCE_NAME) 111 ); CREATE TABLE QRTZ_LOCKS 112 ( 113 LOCK_NAME VARCHAR(40) NOT NULL, 114 PRIMARY KEY (LOCK_NAME) 115 ); INSERT INTO QRTZ_LOCKS values('TRIGGER_ACCESS'); INSERT INTO QRTZ_LOCKS values('JOB_ACCESS'); INSERT INTO QRTZ_LOCKS values('CALENDAR_ACCESS'); INSERT INTO QRTZ_LOCKS values('STATE_ACCESS'); INSERT INTO QRTZ_LOCKS values('MISFIRE_ACCESS'); commit; 116 --------------------- 117 作者:默默同学 118 来源:CSDN 119 原文:https://blog.csdn.net/u012909738/article/details/74454810
2、编写quartz.properties文件
建立 quartz.properties文件把它放在工程的 src 目录下,内容如下:
1 #============================================================================ 2 3 # Configure Main Scheduler Properties 4 5 #============================================================================ 6 7 8 9 org.quartz.scheduler.instanceName = Mscheduler 10 11 org.quartz.scheduler.instanceId = AUTO 12 13 org.quartz.jobStore.clusterCheckinInterval=20000 14 15 16 17 #============================================================================ 18 19 # Configure ThreadPool 20 21 #============================================================================ 22 23 24 25 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 26 27 org.quartz.threadPool.threadCount = 3 28 29 org.quartz.threadPool.threadPriority = 5 30 31 32 33 #============================================================================ 34 35 # Configure JobStore 36 37 #============================================================================ 38 39 40 41 #org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore 42 43 44 45 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 46 47 #org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate 48 49 org.quartz.jobStore.useProperties = true 50 51 #org.quartz.jobStore.dataSource = myDS 52 53 org.quartz.jobStore.tablePrefix = QRTZ_ 54 55 org.quartz.jobStore.isClustered = true 56 57 org.quartz.jobStore.maxMisfiresToHandleAtATime=1 58 59 #============================================================================ 60 61 # Configure Datasources 62 63 #============================================================================ 64 65 66 67 #mysql 68 69 #org.quartz.dataSource.myDS.driver = com.ibm.db2.jcc.DB2Driver 70 71 #org.quartz.dataSource.myDS.URL = jdbc:db2://localhost:50000/db 72 73 #org.quartz.dataSource.myDS.user = db2 74 75 #org.quartz.dataSource.myDS.password = db2 76 77 #org.quartz.dataSource.myDS.maxConnections = 5 78 79 80 81 #oracle 82 83 #org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver 84 85 #org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@localhost:1521:orcl 86 87 #org.quartz.dataSource.myDS.user = scott 88 89 #org.quartz.dataSource.myDS.password = shao 90 91 #org.quartz.dataSource.myDS.maxConnections = 5 92 93 94 95 #For Tomcat 96 97 org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.oracle.OracleDelegate 98 99 #For Weblogic & Websphere 100 101 #org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.WebLogicDelegate 102 103 org.quartz.jobStore.useProperties = false 104 105 org.quartz.jobStore.dataSource = myDS 106 107 108 109 110 111 #JNDI MODE 112 113 #For Tomcat 114 115 org.quartz.dataSource.myDS.jndiURL=java:comp/env/jdbc/oracle 116 117 #For Weblogic & Websphere 118 119 #org.quartz.dataSource.myDS.jndiURL=jdbc/oracle 120 121 122 123 124 125 #============================================================================ 126 127 # Configure Plugins 128 129 #============================================================================ 130 131 132 133 #org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin 134 135 136 137 #org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin 138 139 #org.quartz.plugin.jobInitializer.fileNames = jobs.xml 140 141 #org.quartz.plugin.jobInitializer.overWriteExistingJobs = true 142 143 #org.quartz.plugin.jobInitializer.failOnFileNotFound = true 144 145 #org.quartz.plugin.jobInitializer.scanInterval = 10 146 147 #org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
红色加粗部分是集群需要的配置
核心配置解释如下:
org.quartz.jobStore.class 属性为JobStoreTX,
将任务持久化到数据中。因为集群中节点依赖于数据库来传播Scheduler实例的状态,你只能在使用JDBC JobStore 时应用Quartz 集群。
org.quartz.jobStore.isClustered 属性为true,通知Scheduler实例要它参与到一个集群当中。
org.quartz.jobStore.clusterCheckinInterval
属性定义了Scheduler实例检入到数据库中的频率(单位:毫秒)。
Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;
这能指出一个失败的Scheduler 实例,且当前Scheduler 会以此来接管任何执行失败并可恢复的Job。
通过检入操作,Scheduler也会更新自身的状态记录。clusterChedkinInterval越小,Scheduler节点检查失败的Scheduler 实例就越频繁。默认值是 20000 (即20 秒)
3、修改spring-time.xml文件
1 <?xmlversion="1.0"encoding="UTF-8"?>
2 <!DOCTYPEbeansPUBLIC"-//SPRING//DTD BEAN//EN"
3 "http://www.springframework.org/dtd/spring-beans.dtd">
4 <beans>
5
6 <!-- 调度器lazy-init='false'那么容器启动就会执行调度程序 -->
7 <beanid="startQuertz"lazy-init="false"autowire="no"class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
8 <property name="dataSource" ref="dataSource"/>
9 <property name="configLocation" value="classpath:quartz.properties" />
10 <propertyname="triggers">
11 <list>
12 <refbean="doTime"/>
13 </list>
14 </property>
15 <!-- 允许在Quartz上下文中使用Spring实例工厂 -->
16 <propertyname="applicationContextSchedulerContextKey"value="applicationContext"/>
17 </bean>
18
19 <!-- 触发器 -->
20 <beanid="doTime"class="org.springframework.scheduling.quartz.CronTriggerBean">
21 <propertyname="jobDetail"ref="jobtask"></property>
22 <!-- cron表达式 -->
23 <propertyname="cronExpression"value="10,15,20,25,30,35,40,45,50,55 * * * * ?"></property>
24 </bean>
25
26 <!-- 任务 -->
27 <beanid="jobtask"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
28 <propertyname="targetObject"ref="synUsersJob"></property>
29 <propertyname="targetMethod"value="execute"></property>
30 </bean>
31
32 <!-- 要调用的工作类 -->
33 <beanid="synUsersJob"class="org.leopard.core.quartz.job.SynUsersJob"></bean>
34
35 </beans>
增加红色加粗部分代码,注入数据源和加载quartz.properties文件
OK Quartz集群的配置只有这几步,我们来启动项目。。。
我们启着启着….报错了!
17:00:59,718 ERROR ContextLoader:215 - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'startQuertz' defined in class path resource [config/spring/spring-time.xml]: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException:Couldn't store job: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean [See nested exception: java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean] |
我们主要来看红色部分,主要原因就是这个MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的,因此在把 quartz 的 task 序列化进入数据库时就会抛这个serializable的错误
4、解决serializable错误解决方案
网上查了一下,解决这个问题,目前主要有两种方案:
4.1.修改Spring的源码
博客地址:http://jira.springframework.org/browse/SPR-3797
作者重写了MethodInvokingJobDetailFactoryBean
4.2.通过AOP反射对Spring源码进行切面重构
博客地址:http://blog.csdn.net/lifetragedy/article/details/6212831
根据 QuartzJobBean 来重写一个自己的类,然后使用 SPRING 把这个重写的类(我们就名命它为: MyDetailQuartzJobBean )注入 appContext 中后,再使用 AOP 技术反射出原有的 quartzJobx( 就是开发人员原来已经做好的用于执行 QUARTZ 的 JOB 的执行类 ) 。
两种方式我都进行了测试,都可以解决问题,我们这里先通过第二种方式解决这个bug,没有修改任何Spring的源码
4.2.1、增加MyDetailQuartzJobBean.Java
1 package org.leopard.core.quartz; 2 3 import java.lang.reflect.Method; 4 5 import org.apache.commons.logging.Log; 6 import org.apache.commons.logging.LogFactory; 7 import org.quartz.JobExecutionContext; 8 import org.quartz.JobExecutionException; 9 import org.springframework.context.ApplicationContext; 10 import org.springframework.scheduling.quartz.QuartzJobBean; 11 12 /** 13 * 解决Spring和Quartz整合bug 14 * 15 */ 16 public class MyDetailQuartzJobBean extends QuartzJobBean { 17 protected final Log logger = LogFactory.getLog(getClass()); 18 19 private String targetObject; 20 private String targetMethod; 21 private ApplicationContext ctx; 22 23 protected void executeInternal(JobExecutionContext context) throws JobExecutionException { 24 try { 25 26 logger.info("execute [" + targetObject + "] at once>>>>>>"); 27 Object otargetObject = ctx.getBean(targetObject); 28 Method m = null; 29 try { 30 m = otargetObject.getClass().getMethod(targetMethod, new Class[] {}); 31 32 m.invoke(otargetObject, new Object[] {}); 33 } catch (SecurityException e) { 34 logger.error(e); 35 } catch (NoSuchMethodException e) { 36 logger.error(e); 37 } 38 39 } catch (Exception e) { 40 throw new JobExecutionException(e); 41 } 42 43 } 44 45 public void setApplicationContext(ApplicationContext applicationContext) { 46 this.ctx = applicationContext; 47 } 48 49 public void setTargetObject(String targetObject) { 50 this.targetObject = targetObject; 51 } 52 53 public void setTargetMethod(String targetMethod) { 54 this.targetMethod = targetMethod; 55 } 56 57 }
5、再次修改spring-time.xml文件解决serializable问题
修改后的spring-time.xml文件内容如下:
1 <?xmlversion="1.0"encoding="UTF-8"?>
2 <!DOCTYPEbeansPUBLIC"-//SPRING//DTD BEAN//EN"
3 "http://www.springframework.org/dtd/spring-beans.dtd">
4 <beans>
5
6 <!-- 调度器lazy-init='false'那么容器启动就会执行调度程序 -->
7 <beanid="startQuertz"lazy-init="false"autowire="no"class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
8 <propertyname="dataSource"ref="dataSource"/>
9 <propertyname="configLocation"value="classpath:quartz.properties"/>
10 <propertyname="triggers">
11 <list>
12 <refbean="doTime"/>
13 </list>
14 </property>
15 <!--这个是必须的,QuartzScheduler延时启动,应用启动完后 QuartzScheduler再启动-->
16 <propertyname="startupDelay"value="30"/>
17 <!--这个是可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了-->
18 <propertyname="overwriteExistingJobs"value="true"/>
19 <!-- 允许在Quartz上下文中使用Spring实例工厂 -->
20 <propertyname="applicationContextSchedulerContextKey"value="applicationContext"/>
21 </bean>
22
23 <!-- 触发器 -->
24 <beanid="doTime"class="org.springframework.scheduling.quartz.CronTriggerBean">
25 <propertyname="jobDetail"ref="jobtask"></property>
26 <!-- cron表达式 -->
27 <propertyname="cronExpression"value="10,15,20,25,30,35,40,45,50,55 * * * * ?"></property>
28 </bean>
29
30 <!-- 任务 -->
31 <beanid="jobtask"class="org.springframework.scheduling.quartz.JobDetailBean">
32 <propertyname="jobClass">
33 <value>org.leopard.core.quartz.MyDetailQuartzJobBean</value>
34 </property>
35 <propertyname="jobDataAsMap">
36 <map>
37 <entrykey="targetObject"value="synUsersJob"/>
38 <entrykey="targetMethod"value="execute"/>
39 </map>
40 </property>
41 </bean>
42
43 <!-- 要调用的工作类 -->
44 <beanid="synUsersJob"class="org.leopard.core.quartz.job.SynUsersJob"></bean>
45
46 </beans>
主要看红色加粗部分...
测试
Ok 配置完成,我们把oa_ssh部署到两台tomcat上面,分别启动。
可以看到我们先启动的tomcat控制台打印出日志
另外一台没有打印日志
这时我们把执行定时任务的那台tomcat停止,可以看到等了一会之后,我们的另外一台tomcat会把之前tomcat执行的定时任务接管过来继续执行,我们的集群是成功的。
参考网址:
https://www.cnblogs.com/yinfengjiujian/p/8670026.html
https://blog.csdn.net/u012909738/article/details/74454810
java技术分享:集群环境下的定时任务
...方式有多种,例如JDK自带的Timer+TimerTask方式,Spring3.0以后的调度任务(ScheduledTask),Quartz框架等。Timer+TimerTask是最基本的解决方案,但是比较远古了;Spring自带的ScheduledTask是一个轻量级的定时任务调度器... 查看详情
quartz集群分布式(并发)部署解决方案-spring
项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题,比如需要回滚... 查看详情
springbootspring-security-oauth2默认的authorize和token接口的区别
...的用户授权的token,才能访问用户允许的资源。参考技术Aspring-security-oauth2在集群环境下可行定时任务的实现方式有多种,例如JDK自带的Timer+TimerTask方式,Spring3.0以后的调度任务(ScheduledTask),Quartz等。Timer+TimerTask是最基本的解决... 查看详情
springboot整合quartz集群环境实现动态定时任务配置原
最近做了一个springboot 整合quartz 实现动态定时任务配置,在集群环境下运行的任务。能够对定时任务,动态的进行增删改查,界面效果图如下: 1.在项目中引入jar 2.将需要的表导入数据库 官网上有不... 查看详情
quartz定时任务
...也可以看出Quartz对自己的性能是很有自信的。本文讲解在Spring环境下以注解的方式如何实现Quartz,用后发现这个简单的实在不像话,哪像一个 查看详情
spring+quartz实现定时任务job集群配置
为什么要有集群定时任务?因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真实结果的3倍,那对银行来说是无法想象... 查看详情
spring+quartz集群配置,spring定时任务集群,quartz定时任务集群
Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>& 查看详情
spring与quartz的整合实现定时任务调度[转]
最近在研究Spring中的定时任务功能,最好的办法当然是使用Quartz来实现。对于一个新手来说,花了我不少时间,这里我写个笔记,给大家参考。 我使用的是Maven来管理项目,需要的Jar包我给大家贴出来。 quartz-1.8.5.jar ... 查看详情
springboot整合quartz实现动态的创建或删除定时任务并将定时调度任务持久化到mysql以及quartz集群配置(代码片段)
1.创建quartz数据库并导入quartz的SQL脚本文件quartz源码下载地址:http://www.quartz-scheduler.org/downloads/下载完成后解压,在/src/org/quartz/impl/jdbcjobstore可以找到对应数据库的SQL脚本我这里使用的是MySQL数据库,SQL脚本如下:... 查看详情
springboot整合quartz实现动态的创建或删除定时任务并将定时调度任务持久化到mysql以及quartz集群配置(代码片段)
1.创建quartz数据库并导入quartz的SQL脚本文件quartz源码下载地址:http://www.quartz-scheduler.org/downloads/下载完成后解压,在/src/org/quartz/impl/jdbcjobstore可以找到对应数据库的SQL脚本我这里使用的是MySQL数据库,SQL脚本如下:... 查看详情
springquartz定时任务集群环境下如何实现只在单个节点运行
...行任务,另一个tomcat不执行任务。两个tomcat下边是同样的spring+quartz配置。如何能做到呢?求大神帮忙,谢谢!!!!JavaWeb项目建议使用redis设置一个标志位,如果其中一台跑完了,那么就设置标志位为true,记住一定要把发起跑... 查看详情
spring集成quartz部署在tomcat里任务每次会执行两遍
spring集成quartz在tomcat里部署项目为什么启动的时候任务每次会执行两遍quartz的配置文件在web.xml给spring去加载了参考技术A你是不是同样的定时器配置了两次?你定时器扫描的时间间隔是不是太短?tomcat启动的时间大于或等于运行... 查看详情
分布式定时任务调度框架-quartz学习及实战记录笔记
目录1.Quartz入门2.Quartz中的常用组件之间的关系3.Trigger触发器的介绍4.Quartz配置资源介绍5.Quartz监听器6.SpringBoot整合Quartz实现动态的创建或删除定时任务并将定时调度任务持久化到MySQL以及Quartz集群配置7.分布式定时任务调度框架学... 查看详情
分布式定时任务调度框架-quartz学习及实战记录笔记
目录1.Quartz入门2.Quartz中的常用组件之间的关系3.Trigger触发器的介绍4.Quartz配置资源介绍5.Quartz监听器6.SpringBoot整合Quartz实现动态的创建或删除定时任务并将定时调度任务持久化到MySQL以及Quartz集群配置7.分布式定时任务调度框架学... 查看详情
分布式集群架构场景优化解决方案:分布式调度问题(代码片段)
分布式集群架构场景优化解决方案:分布式调度问题分布式调度问题调度—>定时任务,分布式调度—>在分布式集群环境下定时任务这件事Elastic-job(当当网开源的分布式调度框架)1、定时任务的场景定时任... 查看详情
分布式定时任务调度框架quartz学习与实战记录完整篇(代码片段)
1.Quartz的概念Quartz就是一个基于Java实现的任务调度框架,用于执行你想要执行的任何任务。Quartz是OpenSymphony开源组织在Jobscheduling(定时调度)领域的开源项目,它可以与J2EE和J2SE应用程序相结合也可以单独使用。Q... 查看详情
分布式定时任务调度框架quartz学习与实战记录完整篇(代码片段)
1.Quartz的概念Quartz就是一个基于Java实现的任务调度框架,用于执行你想要执行的任何任务。Quartz是OpenSymphony开源组织在Jobscheduling(定时调度)领域的开源项目,它可以与J2EE和J2SE应用程序相结合也可以单独使用。Q... 查看详情
spring定时任务之quartz(代码片段)
Quartz是一个强大的企业级任务调度框架,Spring中继承并简化了Quartz,下面就看看在Spring中怎样配置Quartz:首先我们来写一个被调度的类:packagecom.taozi.quartz;publicclassQuartzJobpublicvoidexecute()System.out.println("Quart 查看详情