我有以下计划的作业,在多个实例中运行。
@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那里得到这个想法的。
发布于 2020-06-19 13:36:35
最简单的方法是将lockAtMostFor设置为更高的值。它只是一个安全网,以防执行任务的节点死掉,所以这应该不是问题。
如果由于某些原因不能做到这一点,您可以使用extend方法,如您提供的问题中所述。但这意味着你必须手动管理锁。目前还没有允许扩展使用AOP自动创建的锁的功能。
发布于 2020-06-18 21:06:02
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");
}
}
}
}您可以拥有一个像这样的锁,实现一个为给定服务提供锁的lock接口。一旦你有了LockService,就可以用它来限制函数的运行。
这样做的唯一问题是您需要将此代码块添加到所有函数。如果您不想将此代码块添加到所有函数中,那么可以添加一个基于注释的AOP处理程序。
另外,如果获得锁的服务器死了怎么办?我们需要设置每个锁的最大过期时间,或者在锁值中使用时间来识别它是何时添加的,根据锁时间来决定是否可以运行。
https://stackoverflow.com/questions/62450176
复制相似问题