1

我有以下在多个实例中运行的预定作业。

@Scheduled(fixedRate = 10000)
@SchedulerLock(name = "AwesomeJob", lockAtLeastForString = "5S", lockAtMostForString = "5S")
public void awesomeJob() throws InterruptedException {

    for (int i = 0; i < 5; i++) {
        log.info("Processing {}", i);
        Thread.sleep(100000L);
    }
}

我知道如果任务花费的时间比 lockAtMostFor 更长,则结果行为可能是不可预测的。有没有办法通过使用 SimpleLock.extend 方法来避免这种行为?我正在使用 JdbcLockProvider。我从https://github.com/lukas-krecan/ShedLock/issues/151得到了这个想法。

4

2 回答 2

1
interface LockService {
   bool aquireLock(String lockKey, String value);
   bool releaseLock(String lockKey);
}

interface SomeService {
   void do();
}

class Scheduler{
    @AutoWired LockService lockService;
    @Autowired SomeService someService;
    @Scheduled(fixedRate = 10000)
    public void awesomeJob() throws InterruptedException {
      if(lockService.aquireLock("awesomeJob", serverId) ){
        try{
           //call service method 
            someService.do();
        }catch( Exception e ){
          //TODO
        }finally{
          lockService.releaseLock("awesomeJob");
        }
      }   
    }
}

你可以像这个例子一样拥有一个锁,实现一个锁接口,为给定的服务提供一个锁。一旦你有 LockService 使用它来限制功能运行。

唯一的问题是您需要将此代码块添加到所有函数中。如果您不想将此代码块添加到所有函数,请添加基于注释的 AOP 处理程序。

另外,如果获得锁的服务器死了怎么办?我们需要在锁值中设置每个锁的最大过期时间或使用时间来识别它是什么时候添加的,根据锁的时间来决定是否可以运行。

于 2020-06-18T13:06:02.040 回答
1

最简单的方法是设置lockAtMostFor为更高的值。对于执行任务的节点死亡的情况,这只是一个安全网,所以它不应该是一个问题。

如果由于某种原因您不能这样做,您可以使用extend您提供的问题中描述的方法。但这意味着您必须手动管理锁。当前没有允许扩展使用 AOP 自动创建的锁的功能。

于 2020-06-19T05:36:35.473 回答