背景

最近做的一个项目涉及到定时任务操作,定时任务执行不具有幂等性,在服务重启的时候如果中断就会导致结果错误

解决方案

集成 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定时任务执行结束");

    }

}

前台创建这个任务

image-20221127160118113

立即执行一次,

image-20221127160210335

看到此日志后,调用

curl -X POST http://127.0.0.1:8081/restartactuator/shutdown

image-20221127160305678

可以看到打印,会等待 线程池中此任务执行完毕,验证完毕

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐