带有启动锁的春季启动计划任务未按其延迟运行

时间:2019-07-03 11:47:54

标签: java spring-boot scheduled-tasks shedlock

我正在将Spring Boot与shedlock一起使用,以确保我的计划任务仅在一个实例中同时运行。

这是我的配置

@Configuration
@EnableScheduling
@EnableSchedulerLock(mode = 
EnableSchedulerLock.InterceptMode.PROXY_METHOD, 
defaultLockAtMostFor = "PT15M", 
defaultLockAtLeastFor = "PT2M")
public class SchedulerConfig implements SchedulingConfigurer {
@Bean
public LockProvider lockProvider(DataSource dataSource) {
    return new JdbcTemplateLockProvider(dataSource);
}
}

这是我的任务

@Scheduled(fixedDelayString = "2000")
@SchedulerLock(name = "ms.demo.scheduleTaskJob1")
public void scheduleTaskJob1() {
    logger.info("Fixed delay task called every 2 seconds after latest finished Execution Time - {}",dateTimeFormatter.format(LocalDateTime.now()));
}

这是锁表     名称 LOCK_UNTIL LOCKED_AT LOCKED_BY

这里的问题是,当我的任务在19年7月3日第一次运行时06.37.55.858685000 PM

Shedlock将向数据库添加1行,如下所示:

ms.demo.scheduleTaskJob1    03-JUL-19 06.52.37.178573000 PM 03-JUL-19 06.37.55.858685000 PM MB0001

因为默认的LockAtMostFor为15分钟

任务完成后,它将更新此记录以解锁, 现在的行是:

ms.demo.scheduleTaskJob1    03-JUL-19 06.39.37.178573000 PM 03-JUL-19 06.37.55.858685000 PM MB0001

因为defaultLockAtLeastFor为2分钟。

下次执行任务(2019-07-03T18:37:58.434650900Z)时,它将updateRecord以通过sql命令获取锁定

update shedlock set LOCK_UNTIL = '', lock_at = '' , locked_by = 'MB0001' where name = 'MB0001' and LOCK_UNTIL <= '2019-07-03T18:37:58.434650900Z';

无法更新,因此任务将无法运行。

在这里,我必须等待大约2分钟,直到当前时间超过LOCK_UNTIL(03-JUL-19 06.39.37.178573000 PM),而我的任务配置了2s延迟 因此,我的任务不会每2秒运行一次,而是每2分钟运行一次。

3 个答案:

答案 0 :(得分:1)

这是预期的行为。 lockAtLeastFor是用于设置两次运行之间的最小间隔的参数。这意味着您不能比指定值更频繁地运行作业。它有助于解决节点之间的时间同步问题。

在您的特定情况下,作业完成时锁定将保持保持状态,直到指定的2分钟间隔到期(defaultLockAtLeastFor = "PT2M")为止。这次,Spring尝试再次运行作业(因为作业间隔小于锁定间隔),而Shedlock看到该作业被锁定并阻止了新的运行。来源:https://github.com/lukas-krecan/ShedLock(“注释计划的任务”部分)。

要解决此问题,您需要将参数defaultLockAtLeastFor更改为小于或等于2秒,这是您在fixedDelayString = "2000"(“ PT2S”)中指定的值

答案 1 :(得分:0)

您可以在 @EnableSchedulerLock 注释

中尝试@SchedulerLock(name = "ms.demo.scheduleTaskJob1", lockAtLeastFor = "PT2S")使用非默认选项或更改defaultLockAtLeastFor

答案 2 :(得分:0)

确保在 spring 2.x 之后使用@EnableSchedulerLock。