如何使用Spring boot在集群内只执行一次计划任务?
在我的web应用程序中,我有一个使用spring boot开发的计划任务。 我在tomcat集群上运行它,因此在X小时,计划的任务从每个节点开始 我读到了:,所以我遵循了指南,但它不起作用。。以下是我所做的: 我在pom中包含了这些依赖项:如何使用Spring boot在集群内只执行一次计划任务?,spring,spring-boot,cron,locking,scheduled-tasks,Spring,Spring Boot,Cron,Locking,Scheduled Tasks,在我的web应用程序中,我有一个使用spring boot开发的计划任务。 我在tomcat集群上运行它,因此在X小时,计划的任务从每个节点开始 我读到了:,所以我遵循了指南,但它不起作用。。以下是我所做的: 我在pom中包含了这些依赖项: <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring<
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>0.18.2</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc</artifactId>
<version>0.18.2</version>
</dependency>
然后在配置数据源的地方:
@Configuration
@EnableJpaRepositories(basePackages = {"it.repository"}, entityManagerFactoryRef="entityManager", transactionManagerRef="transactionManager")
public class DataSourceMuxConfig {
@Autowired
private Environment environment;
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource.mux")
public DataSource dataSource() throws NamingException {
if(Arrays.asList(environment.getActiveProfiles()).contains("dev")) {
return DataSourceBuilder.create().build();
}else {
Context ctxConfig = new InitialContext();
return (DataSource) ctxConfig.lookup("java:comp/env/jdbc/mux");
}
}
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcLockProvider(dataSource);
}
这是我的日程安排:
@Configuration
@EnableScheduling
@EnableAsync
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10);
}
@Bean
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
}
但它不起作用
集群的每个节点同时执行此计划任务。
为什么?
如何避免使用spring boot同时执行多个任务?我最近实现了一个简单的注释库,在多个节点上只执行一次计划任务。您可以简单地执行以下操作
@Scheduled(cron = "59 59 8 * * *" /* Every day at 8:59:59am */)
@TryLock(name = "emailLock", owner = NODE_NAME, lockFor = TEN_MINUTE)
public void sendEmails() {
List<Email> emails = emailDAO.getEmails();
emails.forEach(email -> sendEmail(email));
}
@计划(cron=“59 59 8***”/*每天上午8:59:59*/)
@TryLock(name=“emailLock”,owner=NODE\u name,lockFor=十分钟)
公众电邮(电邮){
List emails=emailDAO.getEmails();
emails.forEach(email->sendmail(email));
}
有关完整配置,请参阅。您的
锁在哪里至少有一个?如果这项工作完成得足够快,理论上可以运行两个。@DarrenForsyth我会添加它,但我的任务持续10分钟。。也许更多确保锁定它的时间最短,你会想要1run@DarrenForsythe我只希望它被执行一次。。所以我添加了至少=10000的锁。。。为了测试它,我创建了另一个具有相同注释的计划任务,但它们同时启动。您是否尝试过同一应用程序的多个实例来运行完全相同的计划任务。我还将检查事务+shedlock代理是否与执行相冲突
@Scheduled(cron = "59 59 8 * * *" /* Every day at 8:59:59am */)
@TryLock(name = "emailLock", owner = NODE_NAME, lockFor = TEN_MINUTE)
public void sendEmails() {
List<Email> emails = emailDAO.getEmails();
emails.forEach(email -> sendEmail(email));
}