当前位置: 首页 > 网络应用技术

动态配置的时间表设计

时间:2023-03-07 13:44:03 网络应用技术

  定时任务是实际开发中常见的功能类型。例如,通过电子邮件报告将注册用户和前一天的渠道来源数量发送给相关人员。我相信,这种需求已与每个开发合作伙伴打交道。

  您可以使用Linux的crontab来启动处理应用程序,或使用Spring的时间表安排任务,并且还可以使用分布式的调度系统,如果XXL-JOB等。我相信您已经熟悉了汽车并且习惯了到它。直到有一天您收到了新的需求:

  删除任务,无需修改和发布过程;

  停止几分钟,简短地考虑一下,什么样的想法实现?

  本文将从以下部分讨论:

  1.弹簧计划配置和使用。首先,我们将介绍演示的骨架,并根据Spring-Boot完成计划配置;2.数据库固定的时光咨询方案。使用春季时间表定期查询数据库并执行相应的任务。在执行任务策略中,我们将尝试同步和执行异步执行,并分析其优势和缺点;3.基于Taskscheduler动态配置方案。基于数据库旋转或配置中心,Spring Taskscheduler会动态配置以实现动态管理任务的目的。Lock保证只能同时执行;

  在春季启动时使用时间表非常简单。无需添加新的依赖项,只需配置即可。

  1.使用@enablescheduling启用时间表;2.将@scheduled添加到调度方法中;

  首先,我们需要在启动类中添加@enablescheduling注释。该注释将使SchedulingConfiguration配置类启用,以帮助我们完成最基本的配置。

  启用时间表配置后,将@scheduled注释添加到需要计划的方法中。

  runtask任务延迟1s初始化和以5秒为间隔安排。

  计划注释类的详细配置如下:

  cronlinux crontab表达@scheduled(cron =“ */5 * * * * * * * * * * * * * * * * * * * * * * * * *)工作日,每5个s.对于第一个执行,安排了一个固定的固定间隔,因为第一个执行,间隔时间@scheduled(initiariaLdeLay = initiaLdeLay =第一次执行1000,固定= 5000),延迟1秒,然后在5秒内安排安排InitiaLdelayString和initiariaDelay.plan。

  使用数据库来管理任务,并通过旋转计划执行动态调度。首先,我们查看最简单的解决方案:串行执行解决方案。

  总体思维非常简单,过程如下:

  主要部门如下:

  1.在应用程序中启动计划任务(每1秒钟一次)以获取从数据库执行的任务(状态可用,下一个执行时间小于当前时间);2.根据数据库的任务配置信息,按照转换和执行任务的顺序;3.任务完成后,将在计算后获得下一个调度时间,并将其写回数据库;4.等待下一个任务计划。

  核心代码如下:

  该计划很简单,但非常有效。该方案有什么问题?主要的问题是,任务的串行执行将导致后续任务的延迟操作。同时,下一轮检查将是延迟的。

  例如,任务1,task2,task3已按顺序加载。在它们中,任务1需要5秒,任务2需要5秒,而任务3则需要1秒钟。由于这三个任务,任务2将延迟5秒钟,任务3延迟10秒;第二秒。

  调查,核心问题是调度线程和操作线程是相同的线程,并且计划的操作以及任务的操作相互交互。

  让我们看看改进计划:并行执行计划。

  总体执行过程如下:

  与先前的方案相比,新计划引入了线程池,每个任务都对应于线程池,以避免任务之间的相互作用;该任务在线程池中的异步处理以避免调度线程的延迟。特定过程如下:

  1.步骤不变,并且在应用程序中激活了时间表任务(每1秒钟一次),并且定期从数据库执行的任务(可用,下一个执行时间小于当前时间);,将任务提交为专业线程池中执行比例,然后直接返回计划线程;3.任务在线程池中运行,下一个运行时间在结束后进行更新;将任务提交到线程池。如果执行任务,请使用线程池拒绝策略放弃最古老的任务;

  核心代码如下:

  春季调度任务,每1秒运行一次:

  自定义线程池,每个线程池只有一个线程。超过10秒后,将自动恢复线程。当线程饱和时,最古老的任务被直接丢弃:

  最后,在线程池中运行的任务如下:

  该方案的核心是:绕过@schedule注释,并直接配置了基础核心类别任务的弹簧。

  Taskscheduler接口是Spring计划任务的抽象,它也是@schedule背后的无声支持者。首先,我们查看此接口定义。

  它充满了时间表接口。其他人相对简单地叙述。重点是触发接口。首先,查看此接口的定义:

  只有一种方法可以获取下一个执行时间。执行任务后,触发触发器的下一个扣除时间以获取下一个运行时间以实现周期性调度。

  Crontrigger是触发器的最常见实现,以Linux Crontab的形式配置调度任务,例如:

  简要介绍了基本部分,让我们查看数据库动态配置方案。

  总体设计如下:

  咨询数据库的方法仍然如下:详细过程如下:

  1.在应用程序(每1秒钟一次)中启动计划任务,以从数据库中获取所有任务;2.依次遍历任务,与内存中的任务安格里(任务和状态)进行比较,并动态与任务ChedulerAddd或取消调度任务;3. Taskscheduler负责实际任务计划;

  核心代码如下:

  核心辅助类别:

  您是否发现上述方案有一个共同的缺陷:基于数据库的查询获取任务,增加数据库压力。从理论上讲,只有在配置更改时才有必要更新任务。让我们看一下改进计划:基于配置中心的计划。

  总体设计如下:

  核心过程如下:

  1.应用程序启动后,从配置中心获取配置信息,然后完成任务策划器的配置;2.当配置发送更改时,配置中心将主动将配置推向应用程序。当应用程序收到变更通知的变更通知时,调度任务的动态增加或取消;3. Taskscheduler仍然完成任务的实际计划。

  由于手下没有配置中心,因此暂时没有编码,而且这个想法非常简单。护发素可以完成。

  上述方案在单独的环境中运行。如果悬挂了应用程序,则任务计划将停止。为了避免这种情况,需要改进系统的可用性,以实现冗余部署和自动灾难。

  如果部署上述计划将会发生什么?是的,将有一个计划被安排多次派遣的问题。为了确保只有一个任务同时运行,您需要在任务中添加一个队列。在同一时间,由于其锁定存在,当节点有问题时,另一个节点将自动获得安排过程中的锁定,以解决系统的单个问题。

  为简单起见,我们使用Redis的分布式锁。

  Redisson是Redis的丰富客户,它提供了许多高级数据结构。这段时间,我们将使用RLOCK进行相应的保护。

  首先,Redisson启动器是在POM中引入的。

  然后,将redis配置添加到application.properties文件,如下:

  最后,您可以直接使用分布式锁定来保护任务执行。代码如下:

  评论:

  REDIS是一个典型的AP应用程序,而分布式锁定在严格意义上是CP。因此,基于REDIS的分布式锁只能在非Strict环境(例如我们的数据语句要求)中使用。如果您设计资金,则需要使用CP实现,例如Zookeeper等。

  从Spring的时间表开始,本文解释了数据库栏和任务Cheduler配置,以实现调度任务的配置。最后,使用REDIS分布式锁定有效地解决了重复任务的问题和在分布式环境中自动灾难恢复的问题。

  仍然是那句话。建筑设计不是更好的,只有最合适的。学生可以根据自己的需求来承担自己的需求。

  源代码:https://gitee.com/litao851025/books/tree/master/configurable-schedule