我有一个 spring-boot 应用程序,它在生产环境中运行在 2 个实例中,导致计划任务运行两次。为了避免这种情况,我尝试使用 shedlock,如here和here所解释,但它没有任何影响。 我已经在使用 MySql 数据库,我在其中添加了一个
shedlock
表,如上面两个示例中所述。
我的项目结构如下(部分)-
在我的
application.properties
文件中我有这个设置-
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/b4ad?autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
db.username=*****
db.password=*****
在
AppConfig
类中我添加了此注释 -
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
还有这颗豆子 -
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource, "b4ad.shedlock");
}
在
ScheduledManager
课上我有这个计划任务-
@Scheduled(cron = "0 0/1 * * * ?")
@SchedulerLock(name = "deactivateExpiredOrganizations", lockAtLeastFor = "PT5M")
public void deactivateExpiredOrganizations() {
// my code...
}
当我在 2 个实例上本地运行应用程序时(使用
application.properties
文件中的 2 个不同端口),查看日志我可以看到任务在两个实例上运行,同时 shedlock
表保持为空。
根据故障排除部分中的第二项,我似乎错过了一些配置,但我不知道是什么。
任何帮助将不胜感激。
好吧,显然在我的大项目中还有另一个配置类(除了
AppConfig
之外)——一个名为 SqlSpringConfig
,位于 db 模块内。
一旦我把LockProvider
豆子放在那里,一切都会像魅力一样发挥作用
您应该检查您的任务配置实现。
我的项目也有同样的问题。问题出在下面的代码中。
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
我们通过实现 ScheduledTaskRegistrar 添加自定义配置,以使用多线程执行任务。但如果你覆盖configureTasks,shedlock就不起作用。您应该使用@Bean 进行注入。所以,
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("custom-scheduler-");
threadPoolTaskScheduler.initialize();
return threadPoolTaskScheduler;
}
当我将覆盖更改为通过@Bean注入时,效果很好!