ShedLock:运行多个实例多次运行调度程序任务

时间:2017-08-08 07:10:44

标签: java spring scheduled-tasks

如果正在运行多个服务实例,我只使用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上再次运行它。但是这两个实例都开始运行任务。我错过了什么。实施中出了什么问题?有人可以提出任何想法。谢谢!!

6 个答案:

答案 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);
    }
}

解决了这个问题。

相关问题