Quartz定時器使用示例

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




發佈了32 篇原創文章 · 獲贊 11 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章