一、起由
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig implements SchedulingConfigurer {@Beanpublic LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {return new RedisLockProvider(redisConn);}}
SpringBoot Scheduled调度池的线程条数默认为1,多定时任务会积压等待延迟执行。
一下是两种修改方式
(1)@Async注解
@Async注解会异步执行调度任务,避免任务多积压不执行。
也带来了新的问题:任务执行超时没有被分布式锁锁住。
由于任务异步执行,分布式锁代码执行立即返回了,耗费时间几乎为0s,也就是ShedLock配置的lockAtLeastFor生效,lockAtMostFor是永远不生效的。
(2)配置多线程调度池
配置多线程的调度池,可以避免多任务积压,任务执行超时也可以控制。
二、配置多线程调度池
从博客网站里查来的调度池配置方式
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig implements SchedulingConfigurer {@Beanpublic LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {return new RedisLockProvider(redisConn);}@Overridepublic void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {scheduledTaskRegistrar.setScheduler(setTaskExecutors());}@Bean(destroyMethod="shutdown")public ScheduledExecutorService setTaskExecutors(){return Executors.newScheduledThreadPool(10); // 10个线程来处理。}
}
配置后定时任务可以执行,发布到多台机器后,发现所有的机器都在执行相同的定时任务,ShedLock不起作用了。
分析原因:
给scheduledTaskRegistrar注册了一个没有lock的scheduler ScheduledExecutorService,而不是LockableTaskScheduler。
三、正确的配置
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class TimerTaskConfig {@Beanpublic LockProvider scheduledLockConfiguration(RedisConnectionFactory redisConn) {return new RedisLockProvider(redisConn);}@Bean(destroyMethod="shutdown")public ScheduledExecutorService setTaskExecutors(){return Executors.newScheduledThreadPool(10); // 10个线程来处理。}
}