QuartzScheduler 调度器如何使用
最近遇到一个需要自动化训练的需求,用户将训练的要求存入库中,例如:每2天晚上9点训练一次。需要根据不同的要求发送训练命令,
经过调研最终选择使用调度器来实现
<!--Quartz-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
1、写一个自动化迭代的类
package cn.com.wind.schedule; import cn.com.wind.config.EsConfig; import cn.com.wind.config.TranspondProperties; import cn.com.wind.controller.dto.CommonResp; import cn.com.wind.repository.elasticsearch.ESComponent; import cn.com.wind.service.nlp.TrainService; import cn.com.wind.service.nlp.entity.AutoIterationReq; import cn.com.wind.service.nlp.entity.SubmitRequest; import cn.com.wind.util.DateUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.springframework.scheduling.quartz.QuartzJobBean; import javax.annotation.Resource; import java.text.MessageFormat; import static cn.com.wind.utils.TranspondUtils.doPost; /** * @Author qymeng * @Date 2022/5/24 * @Description */ @Slf4j public class AutoIteration extends QuartzJobBean { @Resource private ESComponent esComponent; @Resource private EsConfig esConfig; @Resource private TrainService trainService; @Resource private TranspondProperties properties; /** * 自动化迭代 * @param jobExecutionContext */ @Override protected void executeInternal(JobExecutionContext jobExecutionContext) { JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap(); AutoIterationReq request = JSONObject.parseObject(JSON.toJSONString(jobDataMap), AutoIterationReq.class); if (!request.isWork()) { log.info("无需自动迭代"); } String projectName = request.getProjectName(); String businessName = request.getBusinessName(); String modelVersion = request.getModelVersion(); CommonResp<SubmitRequest> businessConfigInfo = trainService.getBusinessConfigInfo(projectName, businessName, modelVersion); SubmitRequest submitRequest = businessConfigInfo.getData(); String ip = MessageFormat.format(properties.getTrainUrl(), submitRequest.getIp()); //重置样本数量 JSONObject dataSources = submitRequest.getData_sources(); dataSources.put("num", request.getSampleNum()); submitRequest.setData_sources(dataSources); JSONObject jsonResult = JSONObject.parseObject(doPost(submitRequest, ip)); if (jsonResult.getString("msg").equals("操作成功")) { log.info(projectName + "任务({})发送成功,发送地址:{}", businessName, ip); } modelVersion = jsonResult.getString("model_version"); //在配置信息中增加版本号 submitRequest.setModel_version(jsonResult.getString("model_version")); submitRequest.setCreate_time(DateUtils.nowTime()); String id = projectName + "_" + businessName + "_" + modelVersion; //存储配置信息入es esComponent.addData(submitRequest, esConfig.getNlpIndex(), esConfig.getNlpBusinessConfig(), id); log.info("自动化迭代训练已发送"); } }
2、完成一个调度器的实现,注意类名不能使用QuartzScheduler,否则会重名
package cn.com.wind.schedule;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Set;
/**
* @Author qymeng
* @Date 2022/5/24
* @Description
*/
@Component
@Slf4j
public class QuartzSchedulerTemp {
@Autowired
private Scheduler scheduler;
/**
* 执行调度任务
* @param cron
* @param id
* @param jobDataMap
* @throws SchedulerException
*/
public void startJob(String cron, String id, JobDataMap jobDataMap) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(AutoIteration.class)
.setJobData(jobDataMap)
.withIdentity(id).build();
//基于表达式构建触发器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(id)
.withSchedule(cronScheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
if (!scheduler.isShutdown()){
scheduler.start();
}
}
/**
* 删除所有调度任务
* @throws SchedulerException
*/
public void deleteAllJob() throws SchedulerException {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
for(JobKey jobKey:jobKeys){
scheduler.deleteJob(jobKey);
}
}
}
3、设置一个Scheduled定时器,从库中将cron表达式和请求体存入调度器中,并启动调度器
@Autowired
QuartzSchedulerTemp quartzSchedulerTemp;
/**
* 定时器每天拉取配置放入调度器中
*/
@Async
@Scheduled(cron = "0 59 0/1 * * ? ")
public void autoIteration() {
try {
quartzSchedulerTemp.deleteAllJob();
} catch (SchedulerException e) {
log.error("删除所有动态sql定时任务失败");
}
List<Map<String, Object>> recordList = esComponent.searchDataPage(esConfig.getNlpIndex(), esConfig.getNlpAutoIteration()).getRecordList();
if (recordList != null && recordList.size() != 0){
for (Map<String, Object> map : recordList) {
JobDataMap jobDataMap = new JobDataMap(map);
String cron = map.get("cron").toString();
String businessName = map.get("businessName").toString();
try {
log.info("启动自动迭代定时任务,cron:{}, businessName:{}",cron, businessName);
quartzSchedulerTemp.startJob(cron, businessName, jobDataMap);
}catch (Exception e){
log.error("启动定时任务失败!", e);
}
}
}
}
QuartzScheduler
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?