Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring schedule graceful shutdown not working when using a cron scheduled

I have a small standalone application that configures the scheduler to terminate gracefully. With the following configuration:

@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    scheduler.setWaitForTasksToCompleteOnShutdown(true);
    scheduler.setAwaitTerminationSeconds(60);
    return scheduler;
}

I can get it to gracefully terminate the scheduler, but only if I don't have any @Scheduled(cron = ) task. Once I have one of those, no matter what the scheduler will get stuck until timeout. I already tried configuring it also with an executor and do the shutdown/await manually and the effect is exactly the same.

These cron jobs are not even running. They are set to run at a fixed time during the night for example.

Spring version: 4.2.8.RELEASE

This will happen when the timeout reaches the end:

2017.07.28 01:44:56 [Thread-3] WARN  Timed out while waiting for executor 'taskScheduler' to terminate

Any thoughts?

like image 940
rpvilao Avatar asked Jul 28 '17 00:07

rpvilao


People also ask

How do you trigger gracefully shutdown Spring boot application?

In the Spring Boot Document, they said that 'Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit. ' When I click ctrl+c on the shell command, the application can be shutdown gracefully.

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 do I stop a scheduled cron job in Spring boot?

The schedulers do not start or stop. In the real world, it is necessary to stop and restart the scheduler without restarting the spring boot application. The ScheduledAnnotationBeanPostProcessor class allows you to programmatically start and stop the scheduler without having to restart the spring boot application.

How do I stop a scheduled Spring job?

Another way to stop the scheduler would be manually canceling its Future. In the cases with multiple scheduler tasks, then we can maintain the Future map inside of the custom scheduler pool but cancel the corresponding scheduled Future based on scheduler class.


2 Answers

Because by default the ScheduledThreadPoolExecutor will wait for all delayed scheduled tasks to finish executing, even if scheduled tasks aren't running at that time.

Try this below:

@Bean
public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler() {
        private static final long serialVersionUID = -1L;
        @Override
        public void destroy() {
            this.getScheduledThreadPoolExecutor().setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
            super.destroy();
        }
    };
    scheduler.setWaitForTasksToCompleteOnShutdown(true);
    scheduler.setAwaitTerminationSeconds(60);
    return scheduler;
}

Then the ScheduledThreadPoolExecutor will only wait for scheduled tasks which are currently running to finish executing.

like image 57
hkw Avatar answered Sep 27 '22 21:09

hkw


Possible bug in that version of Spring? Refer to jira.spring.io/browse/SPR-15067

like image 24
user1491636 Avatar answered Sep 27 '22 20:09

user1491636