Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Scheduled annotation random delay

Tags:

I am using the @Scheduled annotation from Spring framework to invoke a method. But I have multiple nodes in my setup and I do not want them to all run at exactly the same time. So I'd like to set a random value to the initial delay to offset them from each other.

import org.springframework.scheduling.annotation.Scheduled;

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

Unfortunately, I am only allowed to use a constant expression here. Is there any other way around this? I thought of using Spring expression language.

like image 444
masstroy Avatar asked Jan 09 '15 21:01

masstroy


People also ask

What is @scheduled annotation in spring?

The @EnableScheduling annotation is used to enable the scheduler for your application. This annotation should be added into the main Spring Boot application class file. @SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.

How does @scheduled work in spring?

We can turn any method in a Spring bean for scheduling by adding the @Scheduled annotation to it. The @Scheduled is a method-level annotation applied at runtime to mark the method to be scheduled. It takes one attribute from cron , fixedDelay , or fixedRate for specifying the schedule of execution in different formats.

What is initial delay in spring scheduler?

Initial delay is a period of time that Scheduler is waiting for before the configured task is executed. InitialDelay is a element in @Scheduled annotation that is added to a method.

What is fixed delay in spring scheduler?

Schedule a Task at Fixed Delay In this case, the duration between the end of the last execution and the start of the next execution is fixed. The task always waits until the previous one is finished. This option should be used when it's mandatory that the previous execution is completed before running again.


3 Answers

You can configure the initialDelay through Spring Expression Language:

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

I don't have an IDE to test that code right now, so you may need to adapt that a bit.

like image 166
sk_ Avatar answered Sep 19 '22 12:09

sk_


To make the initial delay randomly somewhere between 0 and the fixedRate try this:

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

Where you define some.delay (but pick a more suitable name) as 10 minutes as a property like so in your application.properties or equivalent.

some.delay = 600000 

Of course if you want to be lazy and hard code it you can always just use ${random.int(600000)}

like image 42
mekazu Avatar answered Sep 20 '22 12:09

mekazu


In this working example, the random delay will be between 5 and 10 seconds.

@Scheduled(fixedDelayString = "#{new Double((T(java.lang.Math).random() + 1) * 5000).intValue()}")
like image 37
yglodt Avatar answered Sep 17 '22 12:09

yglodt