反应式编程-在集群中运行作业

时间:2019-01-26 09:25:48

标签: locking reactive-programming project-reactor

我需要在集群中运行一些作业,一次只能运行一个。 因为我的团队使用了Hazelcast,所以最终得出了一个基于 Hazelcast ILock实现。为了这个问题的目的,我将对此做一个概括。假设我们具有以下接口(可以通过Hazelcast或Reddison(Redis)轻松实现):

public interface MyDistributedLock {

    boolean lock();

    void unlock();

    boolean isLockedByCurrentThread();
}

public interface MyLockDistributedFactory {

    MyDistributedLock getLock(String name);

}

lock 方法在无法获取锁的情况下等待:

private Mono<Void> lock(String name, Publisher<?> publisher, MyLockDistributedFactory myLockFactory) {
    // important to release lock on the same thread as
    // it was aquired    
    Scheduler scheduler = Schedulers.newSingle(name.toLowerCase());

    return Mono.defer(() -> Mono.just(myLockFactory.getLock(name)))
        publishOn(scheduler)
         .doOnNext(MyDistributedLock::lock)
         .doOnNext(lock -> LOGGER.info("Process acquired lock for resource {}", name))
         .flatMapMany(lock -> Flux.from(publisher))
         .publishOn(scheduler) 
         .doFinally(signalType -> {
              MyDistributedLock lock = myLockFactory.getLock(name);
              if (signalType == SignalType.CANCEL) {
                 // cancel ignores publishOn 
                 scheduler.schedule(() -> { 
                    lock.unlock();
                    LOGGER.info("Process released lock for resource {} due to signal type {}", name, signalType);
                 });
              } else if (lock.isLockedByCurrentThread()) {
                 lock.unlock();
                 LOGGER.info("Process released lock for resource {} due to signal type {}", name, signalType);
              }
          })
          .then();
}

一些工作的例子

private Mono<Void> someJobRunEveryOneHourOnEveryNodeInCluster() {
    MyLockDistributedFactory hazelcast = ...;
    return lock("some-job", Flux.just(1,2), hazelcast)
                .repeatWhen(afterOneHour());
}

我想知道这是使用Project Reactor(以及正确的实现)的好方法还是应该以其他方式来完成。请指教。

1 个答案:

答案 0 :(得分:0)

使用Reactor时 是正确的方法,因为您需要将阻塞部分偏移到专用的Scheduler / Thread中。

但是我想说这样的互斥代码通常不是非常适合于反应式编程:您失去了用更少的线程来做更多事情的主要好处之一,如果忘记了,就有可能阻塞应用程序的其他部分publishOn专用线程等...