SpringBoot動態配置定時任務(支持毫秒級)

項目中使用了寫出Apollo進行配置管理,需要實現動態配置Job的執行間隔。
使用動態修改cron表達式的方式可以實現,但是cron表達式不支持毫秒,所以採用以下方式進行配置。
每次配置改動時,將舊的定時任務停掉,重新啓動一個定時任務。

/**
 * shang
 * 2020-02-11 15:41
 */
@Slf4j
@Component
public class OrderJob {

    // 訂單寬表定時同步間隔,單位ms
    @Value("${order.schedule.interval:1000}")
    private Long orderScheduleInterVal;

    private static final String lock = "lock";

    private final Set<String> orderIdSet = Sets.newHashSet();

    @Resource
    private OrderManager orderManager;
    @Resource
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @ApolloConfig
    private Config config;

    private ScheduledFuture<?> future;

    @ApolloConfigChangeListener
    private void configChangeListener(ConfigChangeEvent changeEvent) {
        Set<String> keyNames = config.getPropertyNames();
        for (String key : keyNames) {
            if (StringUtils.equals(key, "order.schedule.interval")) {
                String interVal = config.getProperty(key, "1000");

                if (future != null) {
                    future.cancel(true);
                    log.info("cancel order task");
                }

                PeriodicTrigger periodicTrigger = new PeriodicTrigger(Long.valueOf(interVal), TimeUnit.MILLISECONDS);
                periodicTrigger.setFixedRate(true);
                periodicTrigger.setInitialDelay(1000);

                future = threadPoolTaskScheduler.schedule(this::readOrderIdSet, periodicTrigger);

                log.info("start order task");
            }
            log.info("{}:{}", key, config.getProperty(key, null));
        }
    }

    /**
     * 寫入緩衝set
     *
     * @param orderIds
     */
    public void writeOrderIdSet(Set<String> orderIds) {
        if (CollectionUtils.isEmpty(orderIds)) {
            return;
        }
        synchronized (lock) {
            orderIdSet.addAll(orderIds);
        }
    }

    /**
     * 定時任務從緩衝set裏取
     */
     // 這樣配置無法動態修改執行間隔
//    @Scheduled(fixedRate = 2000)
    public void readOrderIdSet() {
        if (CollectionUtils.isEmpty(orderIdSet)) {
            log.info("緩衝set爲空,定時任務不執行");
            return;
        }
        synchronized (lock) {
            log.info("發送訂單寬表消息:{}條", CollectionUtils.size(orderIdSet));
            // 緩衝區的orderId發kafka消息
            orderManager.sendMessage(orderIdSet);
            // 清空緩衝區
            orderIdSet.clear();
        }
    }

    @PostConstruct
    public void postConstruct() {
        PeriodicTrigger periodicTrigger = new PeriodicTrigger(orderScheduleInterVal, TimeUnit.MILLISECONDS);
        periodicTrigger.setFixedRate(true);
        periodicTrigger.setInitialDelay(1000);

        future = threadPoolTaskScheduler.schedule(this::readOrderIdSet, periodicTrigger);
    }
}

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