锁定龙卷风和多个实例

时间:2013-04-02 14:58:24

标签: python locking tornado

我对Python和Tornado相当陌生,所以请原谅我是否过度复杂了一个长期解决的问题,但我没有找到其他的东西。

我正在为应用程序运行多个Tornado实例(每个服务器多个实例,多个服务器),并且只有一个实例应该执行一些任务,例如在应用程序中安排某些事件。我不想运行执行此任务的专用实例,而是希望采用机会主义的方法,尝试的第一个实例可以完成这项工作。

我的部分解决方案是基于数据库的锁定机制(MongoDB findAndUpdate)。下面的代码似乎运行得很好,但如果这是一个很好的解决方案,或者如果Tornado有现成的锁定和任务分配解决方案,我想得到一些建议。

这是装饰者在进入函数时获取锁定并在之后释放它:

def locking(fn):
    @tornado.gen.engine
    def wrapped(wself, *args, **kwargs):
        @tornado.gen.engine
        def wrapped_callback(*cargs, **ckwargs):
            logging.info("release lock")
            yield tornado.gen.Task(lock.release_lock)
            logging.info("release lock done")
            original_callback(*cargs, **ckwargs)

        logging.info("acquire lock")
        yield tornado.gen.Task(model.SchedulerLock.initialize_lock, area_id=wself.area_id)
        lock = yield tornado.gen.Task(model.SchedulerLock.acquire_lock, area_id=wself.area_id)
        if lock:
            logging.info("acquire lock done")
            original_callback = kwargs['callback']
            kwargs['callback'] = wrapped_callback
            fn(wself, *args, **kwargs)
        else:
            logging.info("acquire lock not possible, postponed")
            ioloop = tornado.ioloop.IOLoop.instance()
            ioloop.add_timeout(datetime.timedelta(seconds=2), functools.partial(wrapped, wself, *args, **kwargs))

    return wrapped

acquire_lock方法返回锁定对象或False

对此有何想法?我知道锁只是解决方案的一半,因为我还需要一种机制来确保一次性任务只完成一次。然而,这可以非常类似地实现。还有什么可以更优雅地解决问题吗?

0 个答案:

没有答案