如果正在运行多个服务实例,我只使用Shedlock
运行scheduler
任务一次。
我跟着documentation,这就是我做的。
这是需要定期运行的功能
@Scheduled(fixedDelayString = "300000")
@SchedulerLock(name = "onlineIngestionTask", lockAtMostFor = 240000, lockAtLeastFor = 240000)
public void pullTasksFromRemote() {
//Code
}
在我的配置类中,我有以下bean
@Bean
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
pom包括
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>0.14.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>0.14.0</version>
</dependency>
我在我的数据库中添加了一个表,jdbc连接到该数据库。
CREATE TABLE shedlock(
name VARCHAR(64),
lock_until TIMESTAMP(3) NULL,
locked_at TIMESTAMP(3) NULL,
locked_by VARCHAR(255),
PRIMARY KEY (name)
)
在此之后,我尝试通过首先在端口8080上运行tha pp来测试功能。然后我使用server.port=9000
在端口9000上再次运行它。但是这两个实例都开始运行任务。我错过了什么。实施中出了什么问题?有人可以提出任何想法。谢谢!!
答案 0 :(得分:2)
我们最近在产品中遇到了这个问题,在这里我们可以看到多次运行锁调度程序。如果您使用的是春季靴子2.2.1.RELEASE或更高版本,请在下面的deps处进行锁住
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>4.8.0</version>
</dependency>
答案 1 :(得分:2)
请尝试在每小时运行以下调度程序的@scheduled
而不是fixedDelayString
中使用cron表达式。
@Scheduled(cron = "0 */1 * * *")
答案 2 :(得分:1)
dlock通过使用数据库索引和约束保证随时具有一个锁。您只需执行以下操作即可。
@Scheduled(cron = "30 30 3 * * *")
@TryLock(name = "onlineIngestionTask", owner = SERVER_NAME, lockFor = 240000)
public void pullTasksFromRemote() {
}
有关使用的信息,请参见article。
答案 3 :(得分:1)
使用Java注释和aop(面向方面)编程自己实现锁是一个很大的挑战。
做起来并不那么复杂。一种:
typedef struct {
typeA a;
typeB b;
typeC c;
typeD d;
} config_t;
rand config_t config[10];
然后在调度程序处理方法周围使用注释。
答案 4 :(得分:0)
两个实例都应该执行任务,但不能同时执行。请查看此示例https://github.com/lukas-krecan/shedlock-example
答案 5 :(得分:0)
Shedlock仅保证给定方法不会在锁定约束内执行两次(因此,请考虑方法执行时间和defaultLockAtMostFor / defaultLockAtLeastFor参数)。默认情况下,Spring仅使用一个线程来执行计划任务,(如果一个作业的运行时间比另一个作业长,或者比defaultLockAtLeastFor长),则可能导致第二个实例在锁定已释放时执行给定的方法。在我的情况下添加
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("scheduled-task-pool-");
threadPoolTaskScheduler.initialize();
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
解决了这个问题。