我有一个类,它有一个注解为@Scheduled的方法
@Component
@Slf4j
public class MyScheduler {
@Scheduled(cron = "${polling-job-cron}") //each minute
public void pollingJob() {
log.info("starting polling job...");
//some work
log.info("polling job finished.");
}
}
字符串
和taskScheduler的配置:
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("mynameofscheduler");
scheduler.setWaitForTasksToCompleteOnShutdown(true);
scheduler.setAwaitTerminationSeconds(30);
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return scheduler;
}
型
我尝试使用等待ContextClosedEvent
的类来使用优雅关闭:
@Component
@Slf4j
public class GracefulShutdown implements ApplicationListener<ContextClosedEvent> {
private final ApplicationContext context;
private final ThreadPoolTaskScheduler taskScheduler;
public GracefulShutdown(ApplicationContext context,
ThreadPoolTaskScheduler taskScheduler) {
this.context = context;
this.taskScheduler = taskScheduler;
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
log.info("Graceful shutdown - start");
log.info("Closing task scheduler");
taskScheduler.shutdown(); //1
taskScheduler.getScheduledThreadPoolExecutor().shutdown(); //2
log.error("Closed task scheduler");
//give k8s a chance to hit in readinessProbe and stop sending requests to this pod
try {
Thread.sleep(80000); //3
} catch (InterruptedException error) {
log.info("error while trying to sleep");
error.printStackTrace();
}
log.info("Closing spring context with startup date, {}, parent: {}, id: {}, name: {}",
context.getStartupDate(), context.getParent(), context.getId(), context.getDisplayName());
((ConfigurableApplicationContext) context).close();
log.info("Graceful shutdown - end");
}
型
即使我关闭了taskScheduler和底层的taskExecutor,新任务仍然由@Scheduled运行。发送SIGTERM时运行GracefulShutdown
的代码,关闭taskScheduler时运行正常。
Graceful shutdown - start
Closing task scheduler
Closed task scheduler
starting polling job...
polling job finished
starting polling job...
polling job finished.
型
threadPoolPrefix被记录在这些行的前面(我已经把上面的行删掉了,因为行太长了,读不懂):
{"timeMillis":1534234560001,"thread":"mynameofscheduler","level":"INFO","loggerName":"myclassr","message":"starting polling job..."
型
我以为可能使用了其他taskScheduler,但我关闭了错误的taskScheduler,但它都是在@Bean
中配置的mynameofscheduler
2条答案
按热度按时间voj3qocg1#
因为默认情况下,ScheduledThreadPoolExecutor将等待所有延迟的计划任务完成执行,即使计划任务当时没有运行。
试试下面这个:
字符串
然后ScheduledThreadPoolExecutor将只等待当前正在运行的计划任务完成执行。
hujrc8aj2#
thx到M. Deinum。我把Spring关流搞砸了。我已经通过注册shutdown hook解决了这个问题:
字符串
现在我不必显式地关闭taskSchedulers。Spring就能完成。