zoukankan      html  css  js  c++  java
  • 升级@Scheduled-分布式定时任务

    最近我在对项目的定时任务服务升级,希望改造成分布式,原本是利用@Scheduled注解实现,然而它并不支持分布式,如果改成quartz或者Spring Cloud Task,感觉对于自己这个简单的项目也没有必要。因此,我准备手写一个简单的支持分布式定时调度任务的框架。

    项目地址是https://github.com/death00/dis-schedule,欢迎大家star、提意见。

    分析

    先分析了一下自己的项目,全都是用的cron表达式,因此执行时间点都是固定的,如果升级为分布式的话,肯定是希望在同一个时间点只有一个应用去执行定时调度。

    场景就变成了:

    多个应用在同一个时间都尝试去执行任务,但最终只有一个应用真正执行。

    这样的话,立马就会让人联想到使用去解决,因为是多个应用,所以就是分布式锁。那么,场景又变了:

    多个应用在同一个时间都尝试去获取分布式锁,只有一个应用能抢到这把锁,抢到锁的应用可以执行定时任务,其他应用则直接放弃,等待下一次执行时间。

    抢锁的时机是每次定时任务执行之前,这又让我联想到了AOP,那么利用注解也就顺理成章了。

    分布式锁

    既然谈到了分布式锁,那么就想一下,这把锁的名称构成是什么。因为定时任务都有自己专门的时间,如果仅仅采用时间的话,那么当有两个任务同时执行时,则就是在抢一把锁,这同样是不合理的。

    所以,锁的名称由两部分组成:任务执行时间、任务名称。

    实现

    实现方案其实已经很成熟了,可以利用Redis数据库Zookeeper等,Redis用的命令是setNx数据库一般都是利用的唯一索引Zookeeper这点我也不是很了解(如果有感兴趣的同学,欢迎在我的项目中添加)。

    我的项目中实现了Redis数据库两种方式,可以看类DisScheduleRedisServiceImplDisScheduleMongodbServiceImpl

    注解

    其次,我自定义了一个注解DisSchedule

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DisSchedule {
    
        /**
         * 定时调度任务的名称(默认是方法名)
         */
        String name() default "";
    
        /**
         * 任务的间隔时间
         */
        int duration();
    
        /**
         * duration的时间单位(默认:分钟)
         */
        DisScheduleUnit unit() default DisScheduleUnit.MINUTES;
    }
    
    1. name代表此次定时调度任务的名称。
    2. duration代表任务的间隔时间,配合unit
    3. unit是自定义的时间单位,有秒、分钟。

    该注解需要配合@Scheduled共同使用,例如:

        @DisSchedule(name = "testSchedule", duration = 1, unit = DisScheduleUnit.MINUTES)
        @Scheduled(cron = "0 0/1 * * * ?")
    

    cron表达式代表1分钟执行一次,且是在整数分钟开始的时候执行,因此@DisSchedule也需要设置为1分钟的时间。

    切面

    接下来,我们只需要在Aspect中定义好切入点(有注解@DisSchedule的方法上),针对这些方法,需要使用Around(环绕增强)进行拦截,因为当抢不到锁的时候,就不允许执行。

    具体可以参考类DisScheduleAspect

    总结

    以上就是我实现的简单的分布式定时任务,虽然简单,但应该可以满足你的基础需求,接下来,我会在这个之上,逐步增加功能(比如监测、失败后预警等)。如果你有什么想法,欢迎在下方留言。

    有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。

    https://death00.github.io/

  • 相关阅读:
    局部加权回归-新的回归思路,为每个样本订制个性化的模型
    Java Spring AOP
    Spring IOC DI 注解开发
    Java Spring IoC
    Pytest自动化测试
    Robot Framework 实现并行测试
    【解决】cannot list resource "services" in API group "" in the namespace "jmbymt"
    Pytest自动化测试
    Kube-prometheus监控jmx指标
    Pytest自动化测试
  • 原文地址:https://www.cnblogs.com/death00/p/11614812.html
Copyright © 2011-2022 走看看