原!总结 quartz集群 定时任务 测试运行ok

由于项目优化重构,想将定时任务从quartz单机模式变成集群或分布式的方式。于是,百度了一圈。。。。修修改改。。。用集群的方式部署定时任务,测试可以。。。

集群?分布式?什么区别?

  集群:同一个业务,部署在多个服务器上

  分布式:一个业务分拆多个子业务,部署在不同的服务器上

或者说

  集群:是指在多台不同的服务器中部署相同应用或服务模块,构成一个集群,通过负载均衡设备对外提供服务。

  分布式:是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务。

平时常用的quartz单机模式

缺点:

  1.单台server如果挂太多定时任务,负载太重,若一个应用部署在两台或多台server上,而定时任务只在一台运行,资源没有合理优化使用。(没有负载均衡)

  2.若运行定时任务的某台server挂了,那么定时任务就不能进行下去,会影响后期业务发展。(没有failover-失效转移策略)

  3.且不说server挂了,如果是运行某个定时任务的线程或相关的某进程非正常退出时(比如进程崩溃,机器断电等),在server恢复后,不会继续执行该task,也会影响业务。

优点:

  1.实现方便,快捷,能满足一般的定时任务需求。

  2.job信息默认存储在内存中,访问快,性能佳。

(Quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,第二种类型叫做JDBC作业存储。)

主要原因是平时常用的quartz存储类型是RAMJobStore,在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。

但是单机模式,如果自己写代码,把job是持久化到数据库中,应该也能实现上面的一些控制。

--------------------------------------我目前的quartz 集群 定时任务----------------------------------------------------

jdk版本:1.8.0_91

quartz版本:1.8.6  ---- 要到官网下载对应的表  quartz-1.8.6.tar\quartz-1.8.6\docs\dbTables\

spring版本:3.2.3

mysql版本:5.1.73

关于quartz的一些基本概念,就不说了,网上很多。quartz集群原理简单说下吧:

1.job要持久化到数据库,因为多台server部署了quartz,是通过同一个数据库的job信息进行感知job的执行情况,因此要有相关的 QRTZ_* 的表来存储这些信息,quartz官网中找

,比如我的quartz是1.8.6,则要去官网中找相应的版本的表,tables_mysql_innodb.sql (我的是mysql数据库,innodb数据库引擎 )。

2.多台server的quartz调度器都是尽最大努力去执行job,通过QRTZ_LOCKS 来锁定job,实现同步机制。(quartz1.8.6版本 QRTZ_LOCKS表 有5条记录:CALENDAR_ACCESS, JOB_ACCESS ,MISFIRE_ACCESS ,STATE_ACCESS ,TRIGGER_ACCESS)

关于行锁的机制:
1、mysql >  set autocommit=0;    //先把mysql设置为不自动提交。
2、 select * from es_locks where lock_name = ‘TRIGGER_ACCESS‘ for update ;     //线程一通过for update 可以把这行锁住
3、 select * from es_locks where lock_name = ‘TRIGGER_ACCESS‘ for update ;     //线程二通过for update 无法获得锁,线程等待。
4、commit;        //线程一通过commit 释放锁
5、 //线程二可以访问到数据,线程不再等待。
所以,通过这个机制,一次只能有一个线程来操作 加锁 -  操作 - 释放锁。  如果 操作 的时间过长的话,会带来集群间的主线程等待。
数据库行锁是一种悲观锁,锁表时其它线程无法查询。

原博文地址:http://blog.csdn.net/guolong1983811/article/details/51501366

quartz定时任务主要是三块东西:1.job  2.trigger  3.schedule    + quartz数据源的配置

直接上代码

1.applicationContext-quartz.xml中job的配置

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

        <!-- 创建同步的话单 -->
    <bean id="createBbossCdrFileTimerJob" class="org.springframework.scheduling.quartz.JobDetailBean">
         <property name="jobClass" value="com.cmcc.open.mssportal.util.MyDetailQuartzJobBean"></property>
          <property name="jobDataAsMap">
            <map>
                <entry key="targetObject" value="createBbossCdrFileTask" />  <!-- 普通java类 CreateBbossCdrFileTask 记得要注入spring容器 -->
                <entry key="targetMethod" value="createBbossCdrFile" />  <!-- 上面类中的定时任务方法 public void createBbossCdrFile() -->
            </map>
        </property>
        <!-- 是否store,当没有trigger关联时 ,默认false -->
          <!-- <property name="durability" value="true" />   -->
        <!-- requestsRecovery属性设置为 true,当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务。 -->
       <!--  <property name="requestsRecovery" value="true" />  若这个为true,则若job执行的进程中断或崩溃,不包括抛出异常,调度器检测到会重新开启执行该job(与org.quartz.jobStore.misfireThreshold设置无关) --> 
    </bean>

    <!-- misfire处理策略
        默认:MISFIRE_INSTRUCTION_SMART_POLICY=0
        MISFIRE_INSTRUCTION_FIRE_ONCE_NOW=1
        MISFIRE_INSTRUCTION_DO_NOTHING=2 -->
    <bean id="createBbossCdrFileTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="createBbossCdrFileTimerJob"></property>
        <property name="cronExpression" value="0/15 * * * * ?"></property>
        <property name="misfireInstruction" value="2"></property>
    </bean>

    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="applicationContextSchedulerContextKey"  value="applicationContext"></property>
          <property name="configLocation" value="classpath:quartz.properties" />
        <property name="triggers">
            <list>
                <ref bean="callRecordsTimerServiceTrigger"/>
            </list>
        </property>
    </bean>
</beans>

其中 dataSource 我是配置在 applicationContext.xml中了
applicationContext.xml
 <!-- 数据库配置文件位置 -->
    <context:property-placeholder location="classpath:datasource.properties" />  //配置在datasource.properties文件中,通过这个引入

    <!-- 配置dbcp数据源 ,其中jdbc相关属性配置在了另外一个配置文件中,在这引用-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <!-- 队列中的最小等待数 -->
        <property name="minIdle" value="${jdbc.minIdle}"></property>
        <!-- 队列中的最大等待数 -->
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>
        <!-- 最长等待时间,单位毫秒 -->
        <property name="maxWait" value="${jdbc.maxWait}"></property>
        <!-- 最大活跃数 -->
        <property name="maxActive" value="${jdbc.maxActive}"></property>
        <property name="initialSize" value="${jdbc.initialSize}"></property>
        <property name="timeBetweenEvictionRunsMillis" value="86400"></property>
        <property name="testWhileIdle" value="true"></property>
        <property name="validationQuery" value="SELECT 1 FROM dual"></property>
    </bean>


其中 com.cmcc.open.mssportal.util.MyDetailQuartzJobBean 
/*
 * Project: zhejiang-refactor-open manager Webapp
 *
 * File Created at 2017年8月23日
 *
 * Copyright 2016 CMCC Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * ZYHY Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license.
 */
package com.cmcc.open.mssportal.util;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

/**
 * @Type MyDetailQuartzJobBean.java
 * @Desc
 * @author
 * @date 2017年8月23日 上午10:22:38
 * @version
 */
//实现StatefulJob接口,成为有状态的job,使Job不能并发执行  <==>相当于 常用的quartz配置 concurrent=false
public class MyDetailQuartzJobBean extends QuartzJobBean /* implements StatefulJob */  {

    protected final Log logger = LogFactory.getLog(getClass());
    private String targetObject;
    private String targetMethod;
    private ApplicationContext ctx;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        try {
            logger.info("execute [" + targetObject + "] at once>>>>>>");
            Object otargetObject = ctx.getBean(targetObject);
            Method m = null;

            try {
                m = otargetObject.getClass().getMethod(targetMethod, new Class[] {});
                m.invoke(otargetObject, new Object[] {});
            } catch (SecurityException e) {
                e.printStackTrace();
                logger.error("-----MyDetailQuartzJobBean SecurityException" + e.getMessage(), e);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                logger.error("-----MyDetailQuartzJobBean NoSuchMethodException" + e.getMessage(),
                        e);
            }
        } catch (Exception e) {
            throw new JobExecutionException(e);
        }
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.ctx = applicationContext;
    }

    public void setTargetObject(String targetObject) {
        this.targetObject = targetObject;
    }

    public void setTargetMethod(String targetMethod) {
        this.targetMethod = targetMethod;
    }

}

2.quartz.properties 配置如下

#Configure Main Scheduler Properties
#调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName = TestScheduler1
#ID设置为自动获取 每一个必须不同
org.quartz.scheduler.instanceId = AUTO  

#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
#org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#Configure JobStore
#容许的最大作业延,若任务延迟时间超过该设定值,就被认为是misfire了,然后会执行关联的misfire策略(trigger中配置), 默认60s
org.quartz.jobStore.misfireThreshold = 1000
#数据保存方式为持久化
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.maxMisfiresToHandleAtATime=10
#打开集群模式
org.quartz.jobStore.isClustered = true
#调度实例失效的检查时间间隔
org.quartz.jobStore.clusterCheckinInterval = 20000
spring配置就不说了,配置文件都要读进去,启动两台tomcat(修改另外一台tomcat的三个端口),不然启动会报错。

tomcat1            tomcat2
admin 8005     8085
http 8080        8088
ajp 8009         8089

测试现象1.启动两台tomcat,两台都会执行不同的job。(同一个job只会在一台tomcat上执行)2.关了其中一台,另外一台会执行所有的job。(上面配置文件applicationContext-quartz.xml中我只配置了一个job,测试的时候我配了多个job)3.再启动刚刚关闭的那台tomcat,定时任务又会分配过来执行(很大概率会分配过来)。4.若在某台tomcat在执行job时,把它强制关了(job没执行完),并且如果这个job设置了requestsRecovery=true,那么另外一台会检测到,然后重新执行该job。
最后谈谈 quartz.properties 中的 org.quartz.jobStore.misfireThreshold设置

理解成 “容许的最大作业延“,我觉得好理解,就是说,如果说某个定时任务的延迟时间,超过了该值,则会被认为是misfire(错过触发)了,紧着会执行相应的misfire策略,quartz1.8.6中有三种策略:
misfire处理策略
    默认:MISFIRE_INSTRUCTION_SMART_POLICY=0 //默认的策略
        MISFIRE_INSTRUCTION_FIRE_ONCE_NOW=1 //fire once now 马上触发一次
        MISFIRE_INSTRUCTION_DO_NOTHING=2 //do nothing 不处理

日志分析(下面的测试 都是MyDetailQuartzJobBean 没有实现 StatefulJob接口,换句话说,都是无状态的job,定时任务可以并发执行)

案例1
quartz1.8.6版本
每隔15秒 执行定时任务 定时任务要执行20s
设置misfirethreshold =2000ms 线程池:线程数量设置为1
默认的quartz misfire处理策略---MISFIRE_INSTRUCTION_SMART_POLICY

[scheduler_Worker-1] 2017-08-24 16:50:00 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:50:00 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:50:00
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:18 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[scheduler_Worker-1] 2017-08-24 16:50:20 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:50:20
[scheduler_Worker-1] 2017-08-24 16:50:20 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:50:20 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:50:20
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:32 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:36 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[scheduler_Worker-1] 2017-08-24 16:50:40 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:50:40
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:40 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[scheduler_Worker-1] 2017-08-24 16:50:40 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:50:40 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:50:40
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:48 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[QuartzScheduler_scheduler-huamao-HP1503564598330_MisfireHandler] 2017-08-24 16:50:52 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.

2017-08-24 16:50:00 -- 2017-08-24 16:50:20
2017-08-24 16:50:15 (这个定时任务 延迟了5s > 设定的misfirethreshold =2s, 被认为misfire了,所以该任务实际执行开始时间为2017-08-24 16:50:20 )

案例2
其他参数同案例1一样
设置misfirethreshold 2000000ms (设置大一点)
[scheduler_Worker-1] 2017-08-24 16:56:45 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:56:45 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:56:45
[scheduler_Worker-1] 2017-08-24 16:57:05 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:57:05
[scheduler_Worker-1] 2017-08-24 16:57:05 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:57:05 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:57:05
[scheduler_Worker-1] 2017-08-24 16:57:25 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:57:25
[scheduler_Worker-1] 2017-08-24 16:57:25 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:57:25 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:57:25
[scheduler_Worker-1] 2017-08-24 16:57:45 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:57:45
[scheduler_Worker-1] 2017-08-24 16:57:45 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:57:45 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:57:45
[scheduler_Worker-1] 2017-08-24 16:58:05 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:58:05
[scheduler_Worker-1] 2017-08-24 16:58:06 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 16:58:06 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 16:58:06
[scheduler_Worker-1] 2017-08-24 16:58:26 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 16:58:26

2017-08-24 16:56:45 -- 2017-08-24 16:57:05 实际 预期 2017-08-24 16:56:45 -- 2017-08-24 16:57:05 || 2017-08-24 16:57:00 -- 2017-08-24 16:57:20
2017-08-24 16:57:05 -- 2017-08-24 16:57:25

原来打算 开始
2017-08-24 16:56:45
2017-08-24 16:57:00
2017-08-24 16:57:15
但是只有一个线程,虽然没有misfire,但是好像是尽最大努力执行



案例3

其他同案例1不变 (产生misfire 用 MISFIRE_INSTRUCTION_DO_NOTHING 策略测试)
trigger的misfire 处理策略
<!-- <property name="misfireInstruction" value="2"></property> -->
<property name="misfireInstructionName" value="MISFIRE_INSTRUCTION_DO_NOTHING"></property>

[scheduler_Worker-1] 2017-08-24 17:32:45 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 17:32:45 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 17:32:45
[QuartzScheduler_scheduler-huamao-HP1503567162825_MisfireHandler] 2017-08-24 17:33:03 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[scheduler_Worker-1] 2017-08-24 17:33:05 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 17:33:05
[scheduler_Worker-1] 2017-08-24 17:33:15 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 17:33:15 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 17:33:15
[QuartzScheduler_scheduler-huamao-HP1503567162825_MisfireHandler] 2017-08-24 17:33:33 INFO -org.quartz.impl.jdbcjobstore.JobStoreSupport.recoverMisfiredJobs(JobStoreSupport.java:963) - Handling 1 trigger(s) that missed their scheduled fire-time.
[scheduler_Worker-1] 2017-08-24 17:33:35 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:96) - ---------createBbossCdrFile task end----------2017-08-24 17:33:35
[scheduler_Worker-1] 2017-08-24 17:33:45 INFO -com.cmcc.open.mssportal.util.MyDetailQuartzJobBean.executeInternal(MyDetailQuartzJobBean.java:42) - execute [createBbossCdrFileTask] at once>>>>>>
[scheduler_Worker-1] 2017-08-24 17:33:45 INFO -com.cmcc.open.ss.timer.service.CreateBbossCdrFileTask.createBbossCdrFile(CreateBbossCdrFileTask.java:86) - ---------createBbossCdrFile task begin----------2017-08-24 17:33:45

预期执行 实际执行
2017-08-24 17:32:45 2017-08-24 17:32:45 -- 2017-08-24 17:33:05
2017-08-24 17:33:00 --> 这个错过啦 因为misfire策略设置donothing ,所以跳过该任务
2017-08-24 17:33:15 --> 开始执行这个
2017-08-24 17:33:30

刚好是按照cron时间表达式实行

案例4

如果 线程池:线程数量设置为10,那么会起来多个线程去执行该job

2017-08-24 17:32:45  线程1执行
2017-08-24 17:33:00   线程2执行
2017-08-24 17:33:15  线程3执行
2017-08-24 17:33:30 线程xxx执行  并不会misfire

案例5

设置:每隔15s执行 定时任务要执行20s(定时任务会超时)

为了防止任务并发,MyDetailQuartzJobBean 实现 StatefulJob接口,使之成为有状态的job

测试结果:

job只有一个线程去一个一个执行,不会并发。如果定时任务预期的执行时间 超时了,但是没有misfire,结果的执行策略是:尽最大努力执行的状态,一个执行完,马上执行下一个

如果超时了,并且超时时间大于org.quartz.jobStore.misfireThreshold的设置,即 misfire了,会执行相应的misfire策略。(若是donothing策略,则完全等价于 concurrent=false的设置)

我们平时常用的非集群,配置 concurrent=false,job不会并发,若是有个定时任务超时了,那就超时的这个任务就不会执行了,只会在按照cron时间表达式 继续执行下一个job。

时间: 2024-10-12 22:07:21

原!总结 quartz集群 定时任务 测试运行ok的相关文章

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

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

(4) Spring中定时任务Quartz集群配置学习

原 来配置的Quartz是通过spring配置文件生效的,发现在非集群式的服务器上运行良好,但是将工程部署到水平集群服务器上去后改定时功能不能正常运 行,没有任何错误日志,于是从jar包.JDK版本.cronExpression到服务器类型,甚至查到了服务器操作系统的类型,都没能找到解决的办 法,后来才知道是集群惹的祸! 详细步骤如下: 1. 按照Quartz集群工作原理 图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知 在数据库中建表.建表模版在Quartz包下docs/d

集群环境下定时调度的解决方案之Quartz集群

集群环境可能出现的问题 在上一篇博客我们介绍了如何在自己的项目中从无到有的添加了Quartz定时调度引擎,其实就是一个Quartz 和Spring的整合过程,很容易实现,但是我们现在企业中项目通常都是部署在集群环境中的,这样我们之前的定时调度就会出现问题了,因为我们的定时任务都加载在内存中的,每个集群节点中的调度器都会去执行,这就会存在重复执行和资源竞争的问题,那么如何来解决这样的问题呢,往下面看吧... 解决方案 在一般的企业中解决类似的问题一般都是在一个note上部署Quartz其他note

spring boot + quartz 集群

spring boot bean配置: @Configuration public class QuartzConfig { @Value("${quartz.scheduler.instanceName}") private String quartzInstanceName; @Value("${org.quartz.dataSource.myDS.driver}") private String myDSDriver; @Value("${org.q

Spring+监听器+Quartz集群(1)——基本配置

先说说项目背景,因为业务需求,项目中有很多定时任务,这自然用到了Quartz这个开源产品.而在这之前使用的Quartz主要是基于内存的,在应用程序启动时,由监听器创建定时任务,为了防止多个应用程序重新创建任务,只能在发布时,在另外的web.xml中禁用监听器.这样系统发布变得麻烦,因为不同的应用程序的配置不同. 除了发布麻烦,还有不能发挥集群的优势,一旦运行任务的服务器崩溃,集群中的其他服务器不能接受定时任务. 为了解决以上的两个问题,在系统中使用Quartz集群,同时考虑到系统中创建定时任务的

jeecg 3.7.1 新版功能,集群定时任务动态发布模块 使用规则

jeecg 3.7.1  集群定时任务动态发布模块 使用规则 新版特性:    支持集群定时任务,支持分布式. 菜单路径: 系统监控-->定时任务 字段说明: 任务ID.任务说明:自定义即可 cron表达式: 定义任务触发的时间规则.提供一个在线生成cron的地址,http://cron.qqe2.com/ 任务类名: 执行定时任务的业务类,实现org.quartz.Job接口,任务触发时系统自动执行execute方法.格式:包名.类名,举例:com.mypackage.ClassName 执行

quartz集群调度机制调研及源码分析---转载

quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的java任务调度框架,功能强大配置灵活.在企业应用中占重要地位.quratz在集群环境中的使用方式是每个企业级系统都要考虑的问题.早在2006年,在ITeye上就有一篇关于quratz集群方案的讨论:http://www.iteye.com/topic/40970 ITeye创始人@Robbin在8楼

(1)quartz集群调度机制调研及源码分析---转载

quartz2.2.1集群调度机制调研及源码分析 原文地址:http://demo.netfoucs.com/gklifg/article/details/27090179 引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的java任务调度框架,功能强大配置灵活.在企业应用中占重要地位.quratz在集群环境中的使用方式是每个企业级系统都要考虑的问题.早在2006年,在ITeye上就有一篇关于qu

项目中使用Quartz集群分享--转载

项目中使用Quartz集群分享--转载 在公司分享了Quartz,发布出来,希望大家讨论补充. CRM使用Quartz集群分享  一:CRM对定时任务的依赖与问题  二:什么是quartz,如何使用,集群,优化  三:CRM中quartz与Spring结合使用 1:CRM对定时任务的依赖与问题  1)依赖  (1)每天晚上的定时任务,通过sql脚本 + crontab方式执行 Xml代码   #crm 0 2 * * * /opt/***/javafiles/***/shell/***_dail