Quartz定时器使用示例
程序员文章站
2022-06-09 11:18:08
...
Quartz原理以及深入理解可以参考:http://blog.itpub.net/11627468/cid-177622-list-1/
使用Quartz来实现定时加载配置进行站点状态检测
项目路径
biz.properties
alarm.cron=0 * 0/1 * * ?
SchedulerService.java
import org.quartz.Job;
import org.quartz.SchedulerException;
import java.util.Date;
public interface SchedulerService {
void addJob(Class<? extends Job> job, String jobName, String cronExpression);
void modifyScheduler(String jobName, String cronExpression) throws SchedulerException;
void pauseScheduler(String jobName) throws SchedulerException;
void resumeScheduler(String jobName) throws SchedulerException;
void removeScheduler(String jobName);
Date getNextFireTime(String jobName) throws SchedulerException;
}
SchedulerServiceImpl.java
import com.ymatou.envmanagement.service.SchedulerService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
*
* @author qianmin 2016年8月18日 下午3:04:02
*
*/
@Service
public class SchedulerServiceImpl implements SchedulerService {
private static final Logger logger = LoggerFactory.getLogger(SchedulerServiceImpl.class);
@Autowired
private Scheduler scheduler;
@Override
@Transactional(value = "mySqlTransactionManager")
public void addJob(Class<? extends Job> job, String jobName, String cronExpression){
try {
List<? extends Trigger> triggerList = scheduler.getTriggersOfJob(new JobKey(jobName));
if (triggerList == null || triggerList.isEmpty()) {
JobDetail jobDetail = JobBuilder.newJob(job)
.withIdentity(jobName)
// .storeDurably(false) //Job是非持久性的,若没有活动的Trigger与之相关联,该Job会从Scheduler中删除掉
// .requestRecovery(true)
// //Scheduler非正常停止(进程停止或机器关闭等)时,Scheduler再次启动时,该Job会重新执行一次
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)
.withMisfireHandlingInstructionDoNothing())
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
else {
modifyScheduler(jobName, cronExpression);
}
} catch (SchedulerException e) {
logger.warn("add job warm some other has done", e);
}
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void modifyScheduler(String jobName, String cronExpression) throws SchedulerException {
// 获取job的原trigger
List<? extends Trigger> triggerList = scheduler.getTriggersOfJob(new JobKey(jobName));
Trigger oldTrigger = triggerList.get(0); // job与trigger一一对应, job有且只有一个trigger
String oldExpr = ((CronTrigger)oldTrigger).getCronExpression();
if(!cronExpression.equals(oldExpr)){
// 借助于原trigger相关联的triggerBuilder修改trigger
TriggerBuilder tb = oldTrigger.getTriggerBuilder();
Trigger newTrigger = tb.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build();
scheduler.rescheduleJob(oldTrigger.getKey(), newTrigger);
}
}
@Override
public void pauseScheduler(String jobName) throws SchedulerException {
scheduler.pauseJob(new JobKey(jobName));
}
@Override
public void resumeScheduler(String jobName) throws SchedulerException {
scheduler.resumeJob(new JobKey(jobName));
}
@Override
@Transactional(value = "mySqlTransactionManager")
public void removeScheduler(String jobName){
JobKey jobKey = new JobKey(jobName);
try {
if(scheduler.checkExists(jobKey)){
scheduler.deleteJob(jobKey);
}
} catch (SchedulerException e) {
logger.warn("removeScheduler warm some other has done", e);
}
}
@Override
public Date getNextFireTime(String jobName) throws SchedulerException {
List<? extends Trigger> triggerList = scheduler.getTriggersOfJob(new JobKey(jobName));
Trigger oldTrigger = triggerList.get(0);
return oldTrigger.getNextFireTime();
}
}
RuleDiscoverer
import com.alibaba.fastjson.JSON;
import com.ymatou.envmanagement.config.BizConfig;
import com.ymatou.envmanagement.domain.service.impl.WebMonitorServiceImpl;
import com.ymatou.envmanagement.holder.RuleHolder;
import com.ymatou.envmanagement.infrastructure.mysqldb.model.NodePo;
import com.ymatou.envmanagement.service.SchedulerService;
import com.ymatou.envmanagement.support.ScheduledExecutorHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Component
public class RuleDiscoverer {
private static final Logger logger = LoggerFactory.getLogger(RuleDiscoverer.class);
@Autowired
private SchedulerService schedulerService;
@Autowired
private WebMonitorServiceImpl webMonitorService;
@Autowired
private BizConfig bizConfig;
private ScheduledExecutorService scheduledExecutorService = ScheduledExecutorHelper.newSingleThreadScheduledExecutor("rule discover");
@PostConstruct
public void execute() {
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
reload();
} catch (Exception ex) {
logger.error("reload rule error", ex);
}
},0L, 1L, TimeUnit.H );
}
/**
* 加载警报配置
*/
@Transactional
public void reload() {
List<NodePo> nodes=webMonitorService.selectActive();
HashMap<String, NodePo> rules = new HashMap<>();
for (NodePo node : nodes) {
rules.put(node.getDomain(), node);
schedulerService.addJob(AlarmRuleJob.class, node.getDomain(), node.getCron());
}
// 已删除的规则 定时任务
RuleHolder.alarmConfigRule.keySet().stream()
.filter(ruleName -> rules.values().stream().noneMatch(rule -> rule.getDomain().equals(ruleName)))
.forEach(ruleName -> schedulerService.removeScheduler(ruleName));
// 替换
RuleHolder.alarmConfigRule = rules;
logger.info("load rule data: {}", JSON.toJSONString(rules));
}
@PreDestroy
public void destroy() {
scheduledExecutorService.shutdownNow();
}
}
AlarmRuleJob
import com.ymatou.envmanagement.infrastructure.util.SpringContextHolder;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author qianmin 2016年9月12日 上午11:05:19
*
*/
@DisallowConcurrentExecution
public class AlarmRuleJob implements Job {
private static final Logger logger = LoggerFactory.getLogger(AlarmRuleJob.class);
@Override
public void execute(JobExecutionContext context) {
try {
SpringContextHolder.getBean(AlarmRuleExecutor.class).execute(context);
} catch (Exception e) {
logger.error("error exec AlarmRuleJob :{}",
context.getJobDetail().getKey().getName(), e);
}
}
}
AlarmRuleExecutor
import com.google.common.collect.Lists;
import com.ymatou.envmanagement.config.BizConfig;
import com.ymatou.envmanagement.domain.service.impl.WebMonitorServiceImpl;
import com.ymatou.envmanagement.infrastructure.mysqldb.model.NodePo;
import com.ymatou.envmanagement.service.NotifyService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.ymatou.envmanagement.constants.Constants;
/**
* FIXME:check biz rule
* @author qianmin 2016年9月12日 上午11:05:19
*
*/
@Component
public class AlarmRuleExecutor{
private static final Logger logger = LoggerFactory.getLogger(AlarmRuleExecutor.class);
private static final DateTimeFormatter FORMATTER_YMDHMS =DateTimeFormatter.ofPattern("yyyyMMddHHmmss") ;
@Autowired
private WebMonitorServiceImpl webMonitorService;
@Autowired
private BizConfig bizConfig;
@Autowired
private NotifyService notifyService;
public void execute(JobExecutionContext context) {
try {
logger.info("exec alarm start. {}", LocalDateTime.now().format(FORMATTER_YMDHMS));
String jobName = context.getJobDetail().getKey().getName();
List<NodePo> nodes = webMonitorService.selectNodeByDomain(jobName);
if (nodes.size()==0) {
logger.info("exec alarm job: {} node==null", jobName);
return;
}
this.execAlarm(nodes.get(0));
logger.info("exec alarm end. {}", LocalDateTime.now().format(FORMATTER_YMDHMS));
} catch (Exception e) {
logger.info("exec alarm excaption. {}"+e.getMessage(), LocalDateTime.now().format(FORMATTER_YMDHMS));
e.printStackTrace();
}
}
/**
* 发送警报
*/
private void execAlarm(NodePo node) throws Exception {
if (node == null) {
return;
}
String port = bizConfig.getClientPort();
if(node.getStressemailactive()!=null && node.getStressemailactive())
{
String stressIp = bizConfig.getStressIp();
String stressUrl="http://"+stressIp+":"+port+"/domain/getwarmup";
if(!webMonitorService.viewState(node,"STRESS",stressUrl,3))
{
notifyService.sendEmail(node.getDomain(),node.getUrl(),"STRESS",node.getEmails(),LocalDateTime.now());
}
}
if(node.getSitemailactive()!=null && node.getSitemailactive())
{
String sitIp = bizConfig.getSitIp();
String sitUrl="http://"+sitIp+":"+port+"/domain/getwarmup";
if(! webMonitorService.viewState(node,"SIT1",sitUrl,3))
{
notifyService.sendEmail(node.getDomain(),node.getUrl(),"SIT",node.getEmails(),LocalDateTime.now());
}
}
if(node.getUatemailactive()!=null && node.getUatemailactive())
{
String uatIp = bizConfig.getUatIp();
String uatUrl="http://"+uatIp+":"+port+"/domain/getwarmup";
if(webMonitorService.viewState(node,"UAT",uatUrl,3))
{
notifyService.sendEmail(node.getDomain(),node.getUrl(),"UAT",node.getEmails(),LocalDateTime.now());
}
}
}
private long getThreshold(Integer threshold, long defaultValue) {
if (threshold == null) {
return defaultValue;
}
return threshold.longValue();
}
/**
* 用分隔符拼接list
* @param address
* @param delimiter
* @return
*/
private String getAddress(List<String> address, String delimiter) {
return address.stream().filter(StringUtils::isNotBlank).distinct().collect(Collectors.joining(delimiter));
}
}
上一篇: 抢答器及计算器的讲解
下一篇: 2020前端面试题--css