欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Quartz定时器使用示例

程序员文章站 2022-06-09 11:18:08
...

Quartz原理以及深入理解可以参考:http://blog.itpub.net/11627468/cid-177622-list-1/

使用Quartz来实现定时加载配置进行站点状态检测

项目路径

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));
    }
}