spring boot + quartz 集群

Posted 沧海一滴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.quartz.dataSource.myDS.URL}")
        private String myDSURL;
       
        @Value("${org.quartz.dataSource.myDS.user}")
        private String myDSUser;
       
        @Value("${org.quartz.dataSource.myDS.password}")
        private String myDSPassword;
       
        @Value("${org.quartz.dataSource.myDS.maxConnections}")
        private String myDSMaxConnections;
       
       
    /**
     * 设置属性
     * @return
     * @throws IOException
     */
    private Properties quartzProperties() throws IOException {
        Properties prop = new Properties();
        prop.put("quartz.scheduler.instanceName", quartzInstanceName);
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
        prop.put("org.quartz.scheduler.jmx.export", "true");
       
        prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
        prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.isClustered", "true");
       
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "20000");
        prop.put("org.quartz.jobStore.dataSource", "myDS");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
        prop.put("org.quartz.jobStore.misfireThreshold", "120000");
        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");
       
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "10");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");
       
        prop.put("org.quartz.dataSource.myDS.driver", myDSDriver);
        prop.put("org.quartz.dataSource.myDS.URL", myDSURL);
        prop.put("org.quartz.dataSource.myDS.user", myDSUser);
        prop.put("org.quartz.dataSource.myDS.password", myDSPassword);
        System.out.println("myDSMaxConnections:" + myDSMaxConnections);
        prop.put("org.quartz.dataSource.myDS.maxConnections", myDSMaxConnections);
       
        prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin");
        prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin");
        prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true");
        return prop;
    }
   
    @Bean  
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("dialogJobTrigger") Trigger cronJobTrigger) throws IOException {  
        SchedulerFactoryBean factory = new SchedulerFactoryBean();  
        // this allows to update triggers in DB when updating settings in config file:  
        //用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了  
        factory.setOverwriteExistingJobs(true);  
        //用于quartz集群,加载quartz数据源  
        //factory.setDataSource(dataSource);    
        //QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动  
        factory.setStartupDelay(10);
        //用于quartz集群,加载quartz数据源配置  
        factory.setQuartzProperties(quartzProperties());
        factory.setAutoStartup(true);
        factory.setApplicationContextSchedulerContextKey("applicationContext");
        //注册触发器  
        factory.setTriggers(cronJobTrigger);
     //直接使用配置文件
//        factory.setConfigLocation(new FileSystemResource(this.getClass().getResource("/quartz.properties").getPath()));
        return factory;  
    }
   
   
    /**
     * 加载job
     * @return
     */
    @Bean  
    public JobDetailFactoryBean updateDialogStatusJobDetail() {  
        return createJobDetail(InvokingJobDetailDetailFactory.class, "updateDialogStatusGroup", "dialogJob");  
    }  

    /**
     * 加载触发器
     * @param jobDetail
     * @return
     */
    @Bean(name = "dialogJobTrigger")  
    public CronTriggerFactoryBean dialogStatusJobTrigger(@Qualifier("updateDialogStatusJobDetail") JobDetail jobDetail) {  
        return dialogStatusTrigger(jobDetail, "0 0 0/1 * * ?");  
    }     

/**     * 创建job工厂     * @param jobClass     * @param groupName     * @param targetObject     * @return     */





   
privatestaticJobDetailFactoryBean createJobDetail(Class<?> jobClass,String groupName,String targetObject){         
JobDetailFactoryBean factoryBean =newJobDetailFactoryBean();          factoryBean
.setJobClass(jobClass);          factoryBean
.setDurability(true);          factoryBean
.setRequestsRecovery(true);        factoryBean
.setGroup(groupName);       
Map<String,String> map =newHashMap<>();        map
.put("targetObject", targetObject);        map
.put("targetMethod","execute");        factoryBean
.setJobDataAsMap(map);       
return factoryBean;     
}     

/**     * 创建触发器工厂     * @param jobDetail     * @param cronExpression     * @return     */




   
privatestaticCronTriggerFactoryBean dialogStatusTrigger(JobDetail jobDetail,String cronExpression){         
CronTriggerFactoryBean factoryBean =newCronTriggerFactoryBean();          factoryBean
.setJobDetail(jobDetail);        factoryBean
.setCronExpression (cronExpression);       
return factoryBean;     
}   

}

  

InvokingJobDetailDetailFactory对象:
public class InvokingJobDetailDetailFactory extends QuartzJobBean{

        // 计划任务所在类  
    private String targetObject;
 
    // 具体需要执行的计划任务  
    private String targetMethod;
   
    private ApplicationContext ctx;
   
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                try {
            Object otargetObject = ctx.getBean(targetObject);
            Method m = null;  
            try {  
                m = otargetObject.getClass().getMethod(targetMethod);  
                m.invoke(otargetObject);  
            } catch (SecurityException e) {  
                e.printStackTrace();  
            } catch (NoSuchMethodException e) {  
                e.printStackTrace();  
            }  
        } 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;  
    }
}

 备注:set方法不能少,setApplicationContext中的applicationContext与factory.setApplicationContextSchedulerContextKey(“applicationContext”)填入的值有关,其原理由InvokingJobDetailDetailFactory父类中的BeanWrapper实现。

sql脚本:–

-- 表的结构 `qrtz_blob_triggers`
--

CREATE TABLE IF NOT EXISTS `qrtz_blob_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(120) NOT NULL,
  `TRIGGER_GROUP` varchar(120) NOT NULL,
  `BLOB_DATA` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_calendars`
--

CREATE TABLE IF NOT EXISTS `qrtz_calendars` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `CALENDAR_NAME` varchar(120) NOT NULL,
  `CALENDAR` blob NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_cron_triggers`
--

CREATE TABLE IF NOT EXISTS `qrtz_cron_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(120) NOT NULL,
  `TRIGGER_GROUP` varchar(120) NOT NULL,
  `CRON_EXPRESSION` varchar(120) NOT NULL,
  `TIME_ZONE_ID` varchar(80) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_fired_triggers`
--

CREATE TABLE IF NOT EXISTS `qrtz_fired_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `ENTRY_ID` varchar(95) NOT NULL,
  `TRIGGER_NAME` varchar(120) NOT NULL,
  `TRIGGER_GROUP` varchar(120) NOT NULL,
  `INSTANCE_NAME` varchar(120) NOT NULL,
  `FIRED_TIME` bigint(13) NOT NULL,
  `SCHED_TIME` bigint(13) NOT NULL,
  `PRIORITY` int(11) NOT NULL,
  `STATE` varchar(16) NOT NULL,
  `JOB_NAME` varchar(120) DEFAULT NULL,
  `JOB_GROUP` varchar(120) DEFAULT NULL,
  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_job_details`
--

CREATE TABLE IF NOT EXISTS `qrtz_job_details` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `JOB_NAME` varchar(120) NOT NULL,
  `JOB_GROUP` varchar(120) NOT NULL,
  `DESCRIPTION` varchar(250) DEFAULT NULL,
  `JOB_CLASS_NAME` varchar(250) NOT NULL,
  `IS_DURABLE` varchar(1) NOT NULL,
  `IS_NONCONCURRENT` varchar(1) NOT NULL,
  `IS_UPDATE_DATA` varchar(1) NOT NULL,
  `REQUESTS_RECOVERY` varchar(1) NOT NULL,
  `JOB_DATA` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_locks`
--

CREATE TABLE IF NOT EXISTS `qrtz_locks` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `LOCK_NAME` varchar(40) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_paused_trigger_grps`
--

CREATE TABLE IF NOT EXISTS `qrtz_paused_trigger_grps` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_GROUP` varchar(120) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- --------------------------------------------------------

--
-- 表的结构 `qrtz_scheduler_state`
--

CREATE TABLE IF NOT EXISTS `qrtz_scheduler_state` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `INSTANCE_NAME` varchar(120) NOT NULL,
  `LAST_CHECKIN_TIME` bigint(13) NOT NULL, 
`CHECKIN_INTERVAL` bigint(13) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

----------------------------------------------------------

--
--表的结构`qrtz_simple_triggers`
--CREATE TABLE IF NOT EXISTS

`qrtz_simple_triggers`( 
`SCHED_NAME` varchar(120) NOT NULL, 
`TRIGGER_NAME` varchar(120) NOT NULL, 
`TRIGGER_GROUP` varchar(120) NOT NULL, 
`REPEAT_COUNT` bigint(7) NOT NULL, 
`REPEAT_INTERVAL` bigint(12) NOT NULL, 
`TIMES_TRIGGERED` bigint(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

----------------------------------------------------------

--
--表的结构`qrtz_simprop_triggers`
--CREATE TABLE IF NOT EXISTS

`qrtz_simprop_triggers`( 
`SCHED_NAME` varchar(120) NOT NULL, 
`TRIGGER_NAME` varchar(120) NOT NULL, 
`TRIGGER_GROUP` varchar(120) NOT NULL, 
`STR_PROP_1` varchar(512) DEFAULT NULL, 
`STR_PROP_2` varchar(512) DEFAULT NULL, 
`STR_PROP_3` varchar(512) DEFAULT NULL, 
`INT_PROP_1`int(11) DEFAULT NULL, 
`INT_PROP_2`int(11) DEFAULT NULL, 
`LONG_PROP_1` bigint(20) DEFAULT NULL, 
`LONG_PROP_2` bigint(20) DEFAULT NULL, 
`DEC_PROP_1`decimal(13,4) DEFAULT NULL, 
`DEC_PROP_2`decimal(13,4) DEFAULT NULL, 
`BOOL_PROP_1` varchar(1) DEFAULT NULL, 
`BOOL_PROP_2` varchar(1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

----------------------------------------------------------

--
--表的结构`qrtz_triggers`
--CREATE TABLE IF NOT EXISTS

`qrtz_triggers`( 
`SCHED_NAME` varchar(120) NOT NULL, 
`TRIGGER_NAME` varchar(120) NOT NULL, 
`TRIGGER_GROUP` varchar(120) NOT NULL, 
`JOB_NAME` varchar(120) NOT NULL, 
`JOB_GROUP` varchar(120) NOT NULL, 
`DESCRIPTION` varchar(250) DEFAULT NULL, 
`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, 
`PREV_FIRE_TIME` bigint(13) DEFAULT NULL, 
`PRIORITY`int(11) DEFAULT NULL, 
`TRIGGER_STATE` varchar(16) NOT NULL, 
`TRIGGER_TYPE` varchar(8) NOT NULL, 
`START_TIME` bigint(13) NOT NULL, 
`END_TIME` bigint(13) DEFAULT NULL, 
`CALENDAR_NAME` varchar(200) DEFAULT NULL, 
`MISFIRE_INSTR` smallint(2) DEFAULT NULL, 
`JOB_DATA` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

--
--Indexesfor dumped tables
--

--
--Indexesfor table `qrtz_blob_triggers`
--ALTER TABLE
`qrtz_blob_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),  ADD KEY
`SCHED_NAME`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_calendars`
--ALTER TABLE
`qrtz_calendars`  ADD PRIMARY KEY
(`SCHED_NAME`,`CALENDAR_NAME`);

--
--Indexesfor table `qrtz_cron_triggers`
--ALTER TABLE
`qrtz_cron_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_fired_triggers`
--ALTER TABLE
`qrtz_fired_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`ENTRY_ID`),  ADD KEY
`IDX_QRTZ_FT_TRIG_INST_NAME`(`SCHED_NAME`,`INSTANCE_NAME`),  ADD KEY
`IDX_QRTZ_FT_INST_JOB_REQ_RCVRY`(`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),  ADD KEY
`IDX_QRTZ_FT_J_G`(`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),  ADD KEY
`IDX_QRTZ_FT_JG`(`SCHED_NAME`,`JOB_GROUP`),  ADD KEY
`IDX_QRTZ_FT_T_G`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),  ADD KEY
`IDX_QRTZ_FT_TG`(`SCHED_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_job_details`
--ALTER TABLE
`qrtz_job_details`  ADD PRIMARY KEY
(`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),  ADD KEY
`IDX_QRTZ_J_REQ_RECOVERY`(`SCHED_NAME`,`REQUESTS_RECOVERY`),  ADD KEY
`IDX_QRTZ_J_GRP`(`SCHED_NAME`,`JOB_GROUP`);

--
--Indexesfor table `qrtz_locks`
--ALTER TABLE
`qrtz_locks`  ADD PRIMARY KEY
(`SCHED_NAME`,`LOCK_NAME`);

--
--Indexesfor table `qrtz_paused_trigger_grps`
--ALTER TABLE
`qrtz_paused_trigger_grps`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_scheduler_state`
--ALTER TABLE
`qrtz_scheduler_state`  ADD PRIMARY KEY
(`SCHED_NAME`,`INSTANCE_NAME`);

--
--Indexesfor table `qrtz_simple_triggers`
--ALTER TABLE
`qrtz_simple_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_simprop_triggers`
--ALTER TABLE
`qrtz_simprop_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--Indexesfor table `qrtz_triggers`
--ALTER TABLE
`qrtz_triggers`  ADD PRIMARY KEY
(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),  ADD KEY
`IDX_QRTZ_T_J`(`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),  ADD KEY
`IDX_QRTZ_T_JG`(`SCHED_NAME`,`JOB_GROUP`),  ADD KEY
`IDX_QRTZ_T_C`(`SCHED_NAME`,`CALENDAR_NAME`(191)),  ADD KEY
`IDX_QRTZ_T_G`(`SCHED_NAME`,`TRIGGER_GROUP`),  ADD KEY
`IDX_QRTZ_T_STATE`(`SCHED_NAME`,`TRIGGER_STATE`),  ADD KEY
`IDX_QRTZ_T_N_STATE`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),  ADD KEY
`IDX_QRTZ_T_N_G_STATE`(`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),  ADD KEY
`IDX_QRTZ_T_NEXT_FIRE_TIME`(`SCHED_NAME`,`NEXT_FIRE_TIME`),  ADD KEY
`IDX_QRTZ_T_NFT_ST`(`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),  ADD KEY
`IDX_QRTZ_T_NFT_MISFIRE`(`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),  ADD KEY
`IDX_QRTZ_T_NFT_ST_MISFIRE`(`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),  ADD KEY
`IDX_QRTZ_T_NFT_ST_MISFIRE_GRP`(`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`);

--
--限制导出的表
--

--
--限制表`qrtz_blob_triggers`
--ALTER TABLE
`qrtz_blob_triggers`  ADD CONSTRAINT
`qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) REFERENCES `qrtz_triggers`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--限制表`qrtz_cron_triggers`
--ALTER TABLE
`qrtz_cron_triggers`  ADD CONSTRAINT
`qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) REFERENCES `qrtz_triggers`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--限制表`qrtz_simple_triggers`
--ALTER TABLE
`qrtz_simple_triggers`  ADD CONSTRAINT
`qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) REFERENCES `qrtz_triggers`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--限制表`qrtz_simprop_triggers`
--ALTER TABLE
`qrtz_simprop_triggers`  ADD CONSTRAINT
`qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) REFERENCES `qrtz_triggers`(`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`);

--
--限制表`qrtz_triggers`
--ALTER TABLE
`qrtz_triggers`  ADD CONSTRAINT
`qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`) REFERENCES `qrtz_job_details`(`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`);


quartz集群实现原理,利用数据库记录job行为,并通过锁机制,使job在同一次中仅运行一次。

 

http://codecloud.net/135188.html

 

以上是关于spring boot + quartz 集群的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot-starter-quartz集群实践

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

spring boot + quartz 集群

Quartz与Spring Boot集成使用

Spring Boot 整合Quartz定时器

spring-boot Quartz 实践