2021-11-05

本文探讨了如何在不重启项目的情况下,通过监听Apollo配置变化动态更新Spring的定时任务调度时间。通过实现ApolloConfigChangeListener接口,捕获配置变更,并根据变更的特定key执行相应的任务重载逻辑,使用ScheduledAnnotationBeanPostProcessor移除并重新加载定时任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

监听Apollo配置,无需重启,动态更新定时任务调度时间

痛点:虽然项目集成了携程的开源框架Apollo配置中心,但是在修改Apollo上配置时,spring启动容器时注册的类无法更新属性,需项目重启重新加载。
本编文章研究下,如何动态更新通过@Schedule注入到容器的定时任务的配置。

  • 监听Apollo发生的变化
//配置监听的namespace
@ApolloConfigChangeListener("application")
    private void onChange(ConfigChangeEvent changeEvent) {
        Set<String> changedKeys = changeEvent.changedKeys();
        for (String key : changedKeys) {
        //拦截以xxx开头的
            if (key.startsWith(PREFIX)) {
                ConfigChange change = changeEvent.getChange(key);
                log.debug("Apollo LAMA config[{}] changed from [{}] to [{}]", key, change.getOldValue(), change.getNewValue());
                switch (key) {
                //监听到目标key
                    case xxx.xxx.xxx:
                    //执行对应逻辑
                      reloadScheduledTask(xxx);
                        break;
                    default:
                        log.info("暂不支持该定时任务的动态更新,key:{}", key);
                }
            }

        }
    }
  • 移除任务,重新加载任务
//注入spring 定时任务控制类
	 @Autowired
    private ScheduledAnnotationBeanPostProcessor postProcessor;
/**
     * 通过 ScheduledAnnotationBeanPostProcessor 终止定时任务-重新启动定时任务
     */
    public void reloadScheduledTask(xxx) {
        // 拿到所有的task
        Set<ScheduledTask> tasks = postProcessor.getScheduledTasks();
        Object taskObject = null;
        for (ScheduledTask task : tasks) {
            Task t = task.getTask();
            ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) t.getRunnable();
            if (StringUtils.equalsIgnoreCase(xxx, StringUtils.substringBefore(runnable.getTarget().getClass().getSimpleName(), "$$"))) {
                taskObject = runnable.getTarget();
                break;
            }
        }
        if (taskObject == null) {
            return;
        }
        log.info("==============重新加载class:{}=============", taskObject.getClass().getName());
        // 调用postProcessBeforeDestruction()方法,将task移除并cancel
        postProcessor.postProcessBeforeDestruction(taskObject, "scheduledTasks");
        // 调用postProcessAfterInitialization()方法重新schedule task
        postProcessor.postProcessAfterInitialization(taskObject, "scheduledTasks");
    }
  • 后面在研究一下,如何动态加载 @Bean 注入的类,实现热部署
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值