narayan-sambireddy
narayan-sambireddy

Reputation: 335

Spring Scheduler code within an App with multiple instances with multiple JVMs

I have a spring scheduler task configured with either of fixedDelay or cron, and have multiple instances of this app running on multiple JVMs.

The default behavior is all the instances are executing the scheduler task.

Is there a way by which we can control this behavior so that only one instance will execute the scheduler task and others don't.

Please let me know if you know any approaches.

Thank you

Upvotes: 3

Views: 5977

Answers (4)

Kotha Nikhila
Kotha Nikhila

Reputation: 41

If my understanding is correct on your question, that you want to run this scheduled job on a single instance, then i think you should look at ShedLock

ShedLock makes sure that your scheduled tasks are executed at most once at the same time. If a task is being executed on one node, it acquires a lock which prevents execution of the same task from another node (or thread). Please note, that if one task is already being executed on one node, execution on other nodes does not wait, it is simply skipped.

Upvotes: 0

Gautham Pushpakumar
Gautham Pushpakumar

Reputation: 1

We had the same problem our three instance were running same job and doing the tasks three times every day. We solved it by making use of Spring batch. Spring batch can have only unique job id so if you start the job with a job id like date it will restricts duplicate jobs to start with same id. In our case we used date like '2020-1-1' (since it runs only once a day) . All three instance tries to start the job with id '2020-1-1' but spring rejects two duplicate job stating already job '2020-1-1' is running.

Upvotes: 0

Akash Bansal
Akash Bansal

Reputation: 71

I have faced similar problem where same scheduled batch job was running on two server where it was intended to be running on one node at a time. But later on I found a solution to not to execute the job if it is already running on other server.

Job someJob = ...
Set<JobExecution> jobs = jobExplorer.findRunningJobExecutions("someJobName");
if (jobs == null || jobs.isEmpty()) {
        jobLauncher.run(someJob, jobParametersBuilder.toJobParameters());
    }
}

So before launching the job, a check is needed if the job is already in execution on other node. Please note that this approach will work only with DB based job repository.

Upvotes: 0

luboskrnac
luboskrnac

Reputation: 24561

We had similar problem. We fixed it like this:

  1. Removed all @Scheduled beans from our Spring Boot services.
  2. Created AWS Lambda function scheduled with desired schedule.
  3. Lambda function hits our top level domain with scheduling request.
  4. Load balancer forwards this request to one of the service instances.

This way we are sure that scheduled task is executed only once across the cluster of our services.

Upvotes: 7

Related Questions