springboot优雅关闭并解决 quartz 调度问题
·
背景
最近做的一个项目涉及到定时任务操作,定时任务执行不具有幂等性,在服务重启的时候如果中断就会导致结果错误
解决方案
集成 actuator 实现 SpringBoot 优雅关闭
集成 actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置文件中配置
management:
endpoint:
health:
show-details: always
shutdown:
# 启用shutdown配置
enabled: true
endpoints:
web:
exposure:
include: '*'
# 自定义管理断点的前缀,安全性考虑
base-path: /restartactuator
server:
port: 8081
# 不允许远程管理连接,安全性考虑
address: 127.0.0.1
通过调用脚本即可实现 springboot 优雅关闭
curl -X POST http://127.0.0.1:8081/restartactuator/shutdown
基于 ApplicationListener 监听Springboot关闭事件,通知等待 quartz 线程池中任务执行完毕,且不schedule新的定时任务
/**
* 系统关闭时,关闭定时任务的执行(等待运行中的任务执行完成)
* <p>监听ContextClosedEvent事件 会在SpringBoot应用关闭,准备销毁Context以及里面的Bean时调用</p>
* <p>因为Bean被销毁之后程序肯定无法执行了,所以需要在这之前触发关闭Quartz</p>
*
* @author azhuzhu
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class QuartzShutdownListener implements ApplicationListener<ContextClosedEvent> {
private final Scheduler quartzScheduler;
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
try {
log.info("-------------------等待运行中的定时任务执行完成-------------------");
// Quartz框架提供的方法,等待所有任务执行完成之后关闭调度器Scheduler,等待期间不再触发新的任务
quartzScheduler.shutdown(true);
log.info("-------------------执行完成,Quartz关闭-------------------");
} catch (SchedulerException e) {
log.info("-------------------Quartz关闭失败-------------------");
}
}
}
演示
我们这边基于 renren 的定时任务实现,创建一个 延时任务,sleep 20s
/**
* 清空测试数据
*/
@Component("demoJob")
public class DemoTask implements ITask{
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void run(String params) throws InterruptedException {
logger.info("returnTask定时任务正在执行");
Thread.sleep(20000);
logger.info("returnTask定时任务执行结束");
}
}
前台创建这个任务

立即执行一次,

看到此日志后,调用
curl -X POST http://127.0.0.1:8081/restartactuator/shutdown

可以看到打印,会等待 线程池中此任务执行完毕,验证完毕
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)