diff --git a/backend/pom.xml b/backend/pom.xml index 8cfbd29b81..34721c92c4 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -162,9 +162,15 @@ - org.quartz-scheduler - quartz - 2.3.0 + com.fit2cloud + quartz-spring-boot-starter + + + org.springframework.boot + spring-boot-autoconfigure + + + 0.0.4 @@ -288,5 +294,43 @@ + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone + + false + + + + jcenter-snapshots + jcenter + https://jcenter.bintray.com/ + + + fit2cloud-enterprise-release + Fit2Cloud Enterprise Release + http://repository.fit2cloud.com/content/repositories/fit2cloud-enterprise-release/ + + true + + + true + + + + fit2cloud + fit2cloud + http://repository.fit2cloud.com/content/groups/public/ + + true + + + true + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/Application.java b/backend/src/main/java/io/metersphere/Application.java index 730b148045..33f41bce49 100644 --- a/backend/src/main/java/io/metersphere/Application.java +++ b/backend/src/main/java/io/metersphere/Application.java @@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.PropertySource; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication(exclude = {QuartzAutoConfiguration.class}) @ServletComponentScan @@ -15,6 +16,7 @@ import org.springframework.context.annotation.PropertySource; KafkaProperties.class, JmeterProperties.class }) +@EnableScheduling @PropertySource(value = {"file:/opt/metersphere/conf/metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true) public class Application { public static void main(String[] args) { diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index ad2ef1c8b3..2d7f0dfa57 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -14,35 +14,24 @@ import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.constants.ScheduleType; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.BeanUtils; -import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; -import io.metersphere.job.QuartzManager; import io.metersphere.job.sechedule.ApiTestJob; -import io.metersphere.job.sechedule.PerformanceTestJob; import io.metersphere.service.FileService; import io.metersphere.service.ScheduleService; -import org.apache.commons.lang3.StringUtils; -import org.quartz.JobDataMap; -import org.quartz.JobKey; -import org.quartz.SchedulerException; -import org.quartz.TriggerKey; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; - import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.UUID; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; @Service diff --git a/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java b/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java new file mode 100644 index 0000000000..38b219d4f5 --- /dev/null +++ b/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java @@ -0,0 +1,93 @@ +package io.metersphere.config; + +import com.fit2cloud.autoconfigure.QuartzProperties; +import com.fit2cloud.quartz.QuartzInstanceIdGenerator; +import com.fit2cloud.quartz.SchedulerStarter; +import com.fit2cloud.quartz.service.QuartzManageService; +import com.fit2cloud.quartz.util.QuartzBeanFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.util.StringUtils; + +import javax.sql.DataSource; +import java.util.Properties; +import java.util.TimeZone; + +@Configuration +@EnableConfigurationProperties(QuartzProperties.class) +@ConditionalOnClass(DataSource.class) +@AutoConfigureAfter(DataSource.class) +public class QuartzAutoConfiguration { + private DataSource dataSource; + + private QuartzProperties properties; + + public QuartzAutoConfiguration(ObjectProvider dataSourceProvider, QuartzProperties properties) { + this.dataSource = dataSourceProvider.getIfAvailable(); + this.properties = properties; + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true") + public SchedulerStarter schedulerStarter() { + return new SchedulerStarter(); + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true") + public QuartzBeanFactory quartzBeanFactory() { + return new QuartzBeanFactory(); + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true") + public QuartzManageService quartzManageService() { + return new QuartzManageService(); + } + + @Bean + @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true") + public TimeZone quartzTimeZone() { + return TimeZone.getTimeZone(properties.getTimeZone()); + } + + @Bean + @ConditionalOnClass(DataSource.class) + @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true") + public SchedulerFactoryBean clusterSchedulerFactoryBean() { + SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); + schedulerFactoryBean.setDataSource(this.dataSource); + schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContextKey"); + schedulerFactoryBean.setOverwriteExistingJobs(true); + schedulerFactoryBean.setStartupDelay(60);// 60 秒之后开始执行定时任务 + Properties props = new Properties(); + props.put("org.quartz.scheduler.instanceName", "clusterScheduler"); + props.put("org.quartz.scheduler.instanceId", "AUTO"); // 集群下的instanceId 必须唯一 + props.put("org.quartz.scheduler.instanceIdGenerator.class", QuartzInstanceIdGenerator.class.getName());// instanceId 生成的方式 + props.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); + props.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); + props.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); + props.put("org.quartz.jobStore.isClustered", "true"); + props.put("org.quartz.jobStore.clusterCheckinInterval", "20000"); + props.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); + props.put("org.quartz.threadPool.threadCount", "10"); + props.put("org.quartz.threadPool.threadPriority", "5"); + props.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true"); + schedulerFactoryBean.setQuartzProperties(props); + if (!StringUtils.isEmpty(this.properties.getSchedulerName())) { + schedulerFactoryBean.setBeanName(this.properties.getSchedulerName()); + } + return schedulerFactoryBean; + } +} diff --git a/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java b/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java index 44f731893c..bb4ce5bcb0 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java @@ -5,10 +5,10 @@ import io.metersphere.api.service.APITestService; import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.commons.utils.LogUtil; -import io.metersphere.job.QuartzManager; -import org.apache.commons.lang3.StringUtils; -import org.quartz.*; +import org.quartz.JobExecutionContext; +import org.quartz.JobKey; +import org.quartz.TriggerKey; + public class ApiTestJob extends MsScheduleJob { @@ -19,12 +19,7 @@ public class ApiTestJob extends MsScheduleJob { } @Override - public void execute(JobExecutionContext context) throws JobExecutionException { - if (StringUtils.isBlank(resourceId)) { - QuartzManager.removeJob(getJobKey(resourceId), getTriggerKey(resourceId)); - } - LogUtil.info("ApiTestSchedule Running: " + resourceId); - LogUtil.info("CronExpression: " + expression); + void businessExecute(JobExecutionContext context) { SaveAPITestRequest request = new SaveAPITestRequest(); request.setId(resourceId); request.setUserId(userId); diff --git a/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java b/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java index 3e947d2bdd..2ddaff0345 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java @@ -1,8 +1,9 @@ package io.metersphere.job.sechedule; -import org.quartz.Job; +import io.metersphere.commons.utils.LogUtil; +import org.quartz.*; -public abstract class MsScheduleJob implements Job{ +public abstract class MsScheduleJob implements Job { protected String resourceId; @@ -10,15 +11,19 @@ public abstract class MsScheduleJob implements Job{ protected String expression; - public void setResourceId(String resourceId) { - this.resourceId = resourceId; + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + + JobKey jobKey = context.getTrigger().getJobKey(); + JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); + this.resourceId = jobDataMap.getString("resourceId"); + this.userId = jobDataMap.getString("userId"); + this.expression = jobDataMap.getString("expression"); + + LogUtil.info(jobKey.getGroup()+ " Running: " + resourceId); + LogUtil.info("CronExpression: " + expression); + businessExecute(context); } - public void setExpression(String expression) { - this.expression = expression; - } - - public void setUserId(String userId) { - this.userId = userId; - } + abstract void businessExecute(JobExecutionContext context); } diff --git a/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java b/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java index 0ef58506e3..e17daeae0c 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java @@ -3,13 +3,9 @@ package io.metersphere.job.sechedule; import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CommonBeanFactory; -import io.metersphere.commons.utils.LogUtil; -import io.metersphere.job.QuartzManager; import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.track.request.testplan.RunTestPlanRequest; -import org.apache.commons.lang3.StringUtils; import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; import org.quartz.JobKey; import org.quartz.TriggerKey; @@ -22,18 +18,12 @@ public class PerformanceTestJob extends MsScheduleJob { } @Override - public void execute(JobExecutionContext context) throws JobExecutionException { - if (StringUtils.isBlank(resourceId)) { - QuartzManager.removeJob(getJobKey(resourceId), getTriggerKey(resourceId)); - } - LogUtil.info("PerformanceTestSchedule Running: " + resourceId); - LogUtil.info("CronExpression: " + expression); + void businessExecute(JobExecutionContext context) { RunTestPlanRequest request = new RunTestPlanRequest(); request.setId(resourceId); request.setUserId(userId); request.setTriggerMode(ReportTriggerMode.SCHEDULE.name()); performanceTestService.run(request); - } public static JobKey getJobKey(String testId) { diff --git a/backend/src/main/java/io/metersphere/job/QuartzManager.java b/backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java similarity index 69% rename from backend/src/main/java/io/metersphere/job/QuartzManager.java rename to backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java index a3d9ff42ab..9fd2aaa882 100644 --- a/backend/src/main/java/io/metersphere/job/QuartzManager.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java @@ -1,12 +1,16 @@ -package io.metersphere.job; +package io.metersphere.job.sechedule; import io.metersphere.commons.utils.LogUtil; import org.quartz.*; -import org.quartz.impl.StdSchedulerFactory; +import org.springframework.stereotype.Component; -public class QuartzManager { +import javax.annotation.Resource; - public static StdSchedulerFactory sf = new StdSchedulerFactory(); +@Component +public class ScheduleManager { + + @Resource + private Scheduler scheduler; /** * 添加 simpleJob @@ -17,24 +21,28 @@ public class QuartzManager { * @param jobDataMap * @throws SchedulerException */ - public static void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class cls, int repeatIntervalTime, - JobDataMap jobDataMap) throws SchedulerException { + public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class cls, int repeatIntervalTime, + JobDataMap jobDataMap) throws SchedulerException { - Scheduler sched = sf.getScheduler(); + JobBuilder jobBuilder = JobBuilder.newJob(cls).withIdentity(jobKey); - JobDetail jd = JobBuilder.newJob(cls).withIdentity(jobKey).setJobData(jobDataMap).build(); + if (jobDataMap != null) { + jobBuilder.usingJobData(jobDataMap); + } + + JobDetail jd = jobBuilder.build(); SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey) .withSchedule( SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(repeatIntervalTime).repeatForever()) .startNow().build(); - sched.scheduleJob(jd, trigger); + scheduler.scheduleJob(jd, trigger); try { - if (!sched.isShutdown()) { - sched.start(); + if (!scheduler.isShutdown()) { + scheduler.start(); } } catch (SchedulerException e) { @@ -44,8 +52,8 @@ public class QuartzManager { } } - public static void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class cls, int repeatIntervalTime) throws SchedulerException { - addSimpleJob(jobKey, triggerKey, cls, repeatIntervalTime); + public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class cls, int repeatIntervalTime) throws SchedulerException { + addSimpleJob(jobKey, triggerKey, cls, repeatIntervalTime); } /** @@ -56,11 +64,14 @@ public class QuartzManager { * @param cron * @param jobDataMap */ - public static void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) { + public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) { try { + + LogUtil.info("addCronJob: " + triggerKey.getName() + "," + triggerKey.getGroup()); + JobBuilder jobBuilder = JobBuilder.newJob(jobClass).withIdentity(jobKey); if (jobDataMap != null) { - jobBuilder.setJobData(jobDataMap); + jobBuilder.usingJobData(jobDataMap); } JobDetail jobDetail = jobBuilder.build(); @@ -74,12 +85,10 @@ public class QuartzManager { CronTrigger trigger = (CronTrigger) triggerBuilder.build(); - Scheduler sched = sf.getScheduler(); + scheduler.scheduleJob(jobDetail, trigger); - sched.scheduleJob(jobDetail, trigger); - - if (!sched.isShutdown()) { - sched.start(); + if (!scheduler.isShutdown()) { + scheduler.start(); } } catch (Exception e) { LogUtil.error(e.getMessage(), e); @@ -87,7 +96,7 @@ public class QuartzManager { } } - public static void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) { + public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) { addCronJob(jobKey, triggerKey, jobClass, cron, null); } @@ -97,14 +106,12 @@ public class QuartzManager { * @param cron * @throws SchedulerException */ - public static void modifyCronJobTime(TriggerKey triggerKey, String cron) throws SchedulerException { - - Scheduler sched = sf.getScheduler(); + public void modifyCronJobTime(TriggerKey triggerKey, String cron) throws SchedulerException { LogUtil.info("modifyCronJobTime: " + triggerKey.getName() + "," + triggerKey.getGroup()); try { - CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); if (trigger == null) { return; @@ -125,7 +132,7 @@ public class QuartzManager { trigger = (CronTrigger) triggerBuilder.build();// 创建Trigger对象 - sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间 + scheduler.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间 /** 方式一 :调用 rescheduleJob 结束 */ /** 方式二:先删除,然后在创建一个新的Job */ @@ -146,15 +153,13 @@ public class QuartzManager { * @param repeatIntervalTime * @throws SchedulerException */ - public static void modifySimpleJobTime(TriggerKey triggerKey, int repeatIntervalTime) throws SchedulerException { - - Scheduler sched = sf.getScheduler(); + public void modifySimpleJobTime(TriggerKey triggerKey, int repeatIntervalTime) throws SchedulerException { try { LogUtil.info("modifySimpleJobTime: " + triggerKey.getName() + "," + triggerKey.getGroup()); - SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(triggerKey); + SimpleTrigger trigger = (SimpleTrigger) scheduler.getTrigger(triggerKey); if (trigger == null) { return; @@ -175,7 +180,7 @@ public class QuartzManager { trigger = (SimpleTrigger) triggerBuilder.build();// 创建Trigger对象 - sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间 + scheduler.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间 /** 方式一 :调用 rescheduleJob 结束 */ @@ -201,19 +206,17 @@ public class QuartzManager { * @param jobKey * @param triggerKey */ - public static void removeJob(JobKey jobKey, TriggerKey triggerKey) { + public void removeJob(JobKey jobKey, TriggerKey triggerKey) { try { LogUtil.info("RemoveJob: " + jobKey.getName() + "," + jobKey.getGroup()); - Scheduler sched = sf.getScheduler(); + scheduler.pauseTrigger(triggerKey); - sched.pauseTrigger(triggerKey); + scheduler.unscheduleJob(triggerKey); - sched.unscheduleJob(triggerKey); - - sched.deleteJob(jobKey); + scheduler.deleteJob(jobKey); } catch (Exception e) { LogUtil.error(e.getMessage(), e); @@ -232,7 +235,7 @@ public class QuartzManager { } - public static void shutdownJobs(Scheduler sched) { + public void shutdownJobs(Scheduler sched) { try { if (!sched.isShutdown()) { sched.shutdown(); @@ -252,12 +255,10 @@ public class QuartzManager { * @param jobDataMap * @throws SchedulerException */ - public static void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, - int intervalTime, JobDataMap jobDataMap) throws SchedulerException { + public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, + int intervalTime, JobDataMap jobDataMap) throws SchedulerException { - Scheduler sched = sf.getScheduler(); - - if (sched.checkExists(triggerKey)) { + if (scheduler.checkExists(triggerKey)) { modifySimpleJobTime(triggerKey, intervalTime); } else { addSimpleJob(jobKey, triggerKey, clz, intervalTime, jobDataMap); @@ -265,7 +266,7 @@ public class QuartzManager { } - public static void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime) throws SchedulerException { + public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime) throws SchedulerException { addOrUpdateSimpleJob(jobKey, triggerKey, clz, intervalTime, null); } @@ -279,23 +280,22 @@ public class QuartzManager { * @param jobDataMap * @throws SchedulerException */ - public static void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) throws SchedulerException { - Scheduler sched = sf.getScheduler(); + public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) throws SchedulerException { LogUtil.info("AddOrUpdateCronJob: " + jobKey.getName() + "," + triggerKey.getGroup()); - if (sched.checkExists(triggerKey)) { + if (scheduler.checkExists(triggerKey)) { modifyCronJobTime(triggerKey, cron); } else { addCronJob(jobKey, triggerKey, jobClass, cron, jobDataMap); } } - public static void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) throws SchedulerException { + public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) throws SchedulerException { addOrUpdateCronJob(jobKey, triggerKey, jobClass, cron, null); } - public static JobDataMap getDefaultJobDataMap(String resourceId, String expression, String userId) { + public JobDataMap getDefaultJobDataMap(String resourceId, String expression, String userId) { JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("resourceId", resourceId); jobDataMap.put("expression", expression); diff --git a/backend/src/main/java/io/metersphere/service/ScheduleService.java b/backend/src/main/java/io/metersphere/service/ScheduleService.java index d15becdeca..4ddb050080 100644 --- a/backend/src/main/java/io/metersphere/service/ScheduleService.java +++ b/backend/src/main/java/io/metersphere/service/ScheduleService.java @@ -4,13 +4,10 @@ import com.alibaba.fastjson.JSON; import io.metersphere.base.domain.Schedule; import io.metersphere.base.domain.ScheduleExample; import io.metersphere.base.mapper.ScheduleMapper; -import io.metersphere.commons.constants.ScheduleGroup; -import io.metersphere.commons.constants.ScheduleType; import io.metersphere.commons.exception.MSException; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.SessionUtils; -import io.metersphere.job.QuartzManager; -import io.metersphere.job.sechedule.ApiTestJob; +import io.metersphere.job.sechedule.ScheduleManager; import org.apache.commons.lang3.StringUtils; import org.quartz.JobKey; import org.quartz.SchedulerException; @@ -28,6 +25,8 @@ public class ScheduleService { @Resource private ScheduleMapper scheduleMapper; + @Resource + private ScheduleManager scheduleManager; public void addSchedule(Schedule schedule) { schedule.setId(UUID.randomUUID().toString()); @@ -73,11 +72,10 @@ public class ScheduleService { try { if (schedule.getEnable()) { LogUtil.error("初始化任务:" + JSON.toJSONString(schedule)); - QuartzManager.addOrUpdateCronJob(new JobKey(schedule.getKey(), schedule.getGroup()), + scheduleManager.addOrUpdateCronJob(new JobKey(schedule.getKey(), schedule.getGroup()), new TriggerKey(schedule.getKey(), schedule.getGroup()), Class.forName(schedule.getJob()), schedule.getValue(), - QuartzManager.getDefaultJobDataMap(schedule.getResourceId(), schedule.getValue(), schedule.getUserId())); + scheduleManager.getDefaultJobDataMap(schedule.getResourceId(), schedule.getValue(), schedule.getUserId())); } - Thread.sleep(1*60*1000); } catch (Exception e) { LogUtil.error("初始化任务失败", e); e.printStackTrace(); @@ -100,14 +98,14 @@ public class ScheduleService { String cronExpression = request.getValue(); if (enable != null && enable && StringUtils.isNotBlank(cronExpression)) { try { - QuartzManager.addOrUpdateCronJob(jobKey, triggerKey, clazz, cronExpression, QuartzManager.getDefaultJobDataMap(request.getResourceId(), cronExpression, SessionUtils.getUser().getId())); + scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, clazz, cronExpression, scheduleManager.getDefaultJobDataMap(request.getResourceId(), cronExpression, SessionUtils.getUser().getId())); } catch (SchedulerException e) { LogUtil.error(e.getMessage(), e); MSException.throwException("定时任务开启异常"); } } else { try { - QuartzManager.removeJob(jobKey, triggerKey); + scheduleManager.removeJob(jobKey, triggerKey); } catch (Exception e) { MSException.throwException("定时任务关闭异常"); } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 2afe88e538..1729fe9d3a 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -64,4 +64,8 @@ kafka.ssl.provider= kafka.ssl.truststore-type= # jmeter -jmeter.home=/opt/jmeter \ No newline at end of file +jmeter.home=/opt/jmeter + +# quartz +quartz.enabled=true +quartz.scheduler-name=msServerJob \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V5__schedule.sql b/backend/src/main/resources/db/migration/V5__schedule.sql index 449a53f4dd..2d7302148a 100644 --- a/backend/src/main/resources/db/migration/V5__schedule.sql +++ b/backend/src/main/resources/db/migration/V5__schedule.sql @@ -1,3 +1,155 @@ +-- quartz start +CREATE TABLE `qrtz_job_details` ( + `SCHED_NAME` varchar(120) NOT NULL, + `JOB_NAME` varchar(200) NOT NULL, + `JOB_GROUP` varchar(200) 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, + PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), + KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + `JOB_NAME` varchar(200) NOT NULL, + `JOB_GROUP` varchar(200) 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, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), + KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), + KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), + KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_blob_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + `BLOB_DATA` blob, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_calendars` ( + `SCHED_NAME` varchar(120) NOT NULL, + `CALENDAR_NAME` varchar(200) NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_cron_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + `CRON_EXPRESSION` varchar(120) NOT NULL, + `TIME_ZONE_ID` varchar(80) DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_fired_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `ENTRY_ID` varchar(95) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + `INSTANCE_NAME` varchar(200) 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(200) DEFAULT NULL, + `JOB_GROUP` varchar(200) DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), + KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), + KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), + KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), + KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_locks` ( + `SCHED_NAME` varchar(120) NOT NULL, + `LOCK_NAME` varchar(40) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_paused_trigger_grps` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_scheduler_state` ( + `SCHED_NAME` varchar(120) NOT NULL, + `INSTANCE_NAME` varchar(200) NOT NULL, + `LAST_CHECKIN_TIME` bigint(13) NOT NULL, + `CHECKIN_INTERVAL` bigint(13) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_simple_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) NOT NULL, + `REPEAT_COUNT` bigint(7) NOT NULL, + `REPEAT_INTERVAL` bigint(12) NOT NULL, + `TIMES_TRIGGERED` bigint(10) NOT NULL, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `qrtz_simprop_triggers` ( + `SCHED_NAME` varchar(120) NOT NULL, + `TRIGGER_NAME` varchar(200) NOT NULL, + `TRIGGER_GROUP` varchar(200) 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, + PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- quartz end + CREATE TABLE IF NOT EXISTS `schedule` ( `id` varchar(50) NOT NULL COMMENT 'Schedule ID', `key` varchar(50) NOT NULL COMMENT 'Schedule Key',