Quartz框架(八)— Quartz實現異步通知

Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore數據庫表字段詳解
Quartz框架(三)—任務的並行/串行執行
Quartz框架(四)—misfire處理機制
Quartz框架(五)— 有狀態的job和無狀態job
Quartz框架(六)— Trigger狀態轉換
Quartz框架(七)— Quartz集羣+實戰運用
Quartz框架(八)— Quartz實現異步通知

使用Quartz如何實現梯度的異步通知呢?

1. 一個Job綁定多個觸發器

一個Trigger只能綁定一個Job,但是一個Job可以綁定多個Trigger。

那麼,若是我們將一個Job上綁定多個觸發器,且每個觸發器只是觸發一次的話,那麼,實際上我們便可以實現階梯式的異步通知。

程序代碼

public class TestQuartzForMoreJob {

    Logger logger=LoggerFactory.getLogger(TestQuartzForMoreJob.class);

    @Test
    public void test() {
        SimpleScheduleBuilder scheduleBuilder1=SimpleScheduleBuilder.repeatSecondlyForTotalCount(1);
        //任務
        JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
                .withIdentity("job1", "job_group1")
                .storeDurably()
                .build();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = new Date();
        Date date1 = addSecond(date, 5);
        Date date2 = addSecond(date, 15);
        //日誌打印
        logger.info("獲取到任務的時間:"+sdf.format(date));
        logger.info("第一次通知的時間:"+sdf.format(date1));
        logger.info("第二次通知的時間:"+sdf.format(date2));
        //觸發器1
        SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1")
                .withSchedule(scheduleBuilder1)
                .startAt(date1)
                .forJob(new JobKey("job1", "job_group1"))
                .build();
        //觸發器2
        SimpleTrigger trigger2 = newTrigger().withIdentity("trigger2", "group1")
                .withSchedule(scheduleBuilder1)
                .forJob(new JobKey("job1", "job_group1"))
                .startAt(date2)
                .build();
        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //多觸發器關聯
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.scheduleJob(trigger2);
            scheduler.start();
            Thread.sleep(100000);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static Date addSecond(Date date, int second) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(date);
//        calendar.add(Calendar.MINUTE, minute);
        calendar.add(Calendar.SECOND, second);
        return calendar.getTime();
    }
}

日誌打印

17:19:53.215 [main] INFO com.com.tellme.TestQuartzForMoreJob - 獲取到任務的時間:2019-07-09 05:19:53
17:19:53.220 [main] INFO com.com.tellme.TestQuartzForMoreJob - 第一次通知的時間:2019-07-09 05:19:58
17:19:53.220 [main] INFO com.com.tellme.TestQuartzForMoreJob - 第二次通知的時間:2019-07-09 05:20:08
17:19:58.218 [DefaultQuartzScheduler_Worker-1] INFO com.com.tellme.HelloQuartz - 多觸發器測試,時間:2019-07-09 05:19:58
17:20:08.211 [DefaultQuartzScheduler_Worker-2] INFO com.com.tellme.HelloQuartz - 多觸發器測試,時間:2019-07-09 05:20:08

2. 定時輪詢數據庫

這個思想是將需要異步通知的數據保存到數據表中,該表的結構有這麼幾個主要的字段:

CREATE TABLE `yy_notify` (
  `TXN_ID` varchar(32) NOT NULL COMMENT '系統單號',
  `SERVICE_ID` varchar(255) NOT NULL COMMENT 'Spring Bean id',
  `SCAN_STATUS` varchar(2) DEFAULT NULL COMMENT '掃描狀態(00:待掃描,01:不掃描)',
  `SCAN_TIMES` int(1) DEFAULT '0' COMMENT '掃描次數',
  `NEXT_SCAN_TIME` timestamp NULL DEFAULT NULL COMMENT '下次掃描時間,用於梯度查詢場景',
  `NOTIFY_STATUS` varchar(255) DEFAULT NULL COMMENT '(02-通知成功,03-通知返回失敗,01-未通知)',
  `CREATE_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `MODIFY_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  PRIMARY KEY (`TXN_ID`) USING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

每1分鐘輪詢一次該表,將該表中NOTIFY_STATUS=未通知,SCAN_TIMES<=最大掃描次數,NEXT_SCAN_TIME<當前時間的數據取出,直接調用通知邏輯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章