Spring @Scheduled注解随机延迟

Spring @Scheduled annotation random delay

我正在使用 Spring 框架中的 @Scheduled 注释来调用一个方法。但是我的设置中有多个节点,我不希望它们同时全部 运行。所以我想给初始延迟设置一个随机值来抵消它们。

import org.springframework.scheduling.annotation.Scheduled;

@Scheduled(fixedRate = 600000, initialDelay = <random number between 0 and 10 minutes> )

不幸的是,我在这里只能使用常量表达式。有没有其他办法解决这个问题?我想到了使用 Spring 表达式语言。

您可以通过Spring表达式语言配置initialDelay:

@Scheduled(fixedRate = 600000, initialDelayString = "#{ T(java.util.concurrent.ThreadLocalRandom).current().nextInt(10*60*1000) }" )

我现在没有 IDE 来测试该代码,因此您可能需要稍微调整一下。

要使初始延迟随机地介于 0 和 fixedRate 之间,试试这个:

@Scheduled(fixedDelayString = "${some.delay}", initialDelayString = "${random.int(${some.delay})}")

您将 some.delay(但选择一个更合适的名称)定义为 10 分钟,就像 application.properties 或等效项中的 属性 一样。

some.delay = 600000

当然,如果你想偷懒和硬编码,你总是可以使用 ${random.int(600000)}

请记住,initialDelayString 仅在启动时计算一次,然后在计划作业时使用相同的值。

参见org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#processScheduled

在此工作示例中,随机延迟将在 5 到 10 秒之间。

@Scheduled(fixedDelayString = "#{new Double((T(java.lang.Math).random() + 1) * 5000).intValue()}")

或者您可以在函数末尾添加 Thread.sleep(...)。

@Scheduled(fixedDelay = 10000)
public void replicateData() {

    ... do stuff ...

    try {
        Thread.sleep(RandomUtils.nextLong(1000, 10000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

在科特林中这有效:

@Component
class MyJob {
   companion object {
      const val INTERVAL = 24*3600*1000L // once a day
   }

   @Scheduled(fixedRate = INTERVAL, initialDelayString = "${random.long($INTERVAL)}")
   fun doDaily() {
      ...
   }
}

这应该有效

@Scheduled(fixedRate = 600000, initialDelay = "#{new java.util.Random().nextInt(700)}")

通过这个简单的测试验证了它:

    @Test
    public void testSpEL() {
       ExpressionParser parser = new SpelExpressionParser();
       Expression exp = parser.parseExpression("new java.util.Random().nextInt(500)");
       Integer value =(Integer) exp.getValue();
       Assertions.assertThat(value).isNotNull();
}