私は Python と Tornado にかなり慣れていないので、長い間解決されてきた問題を過度に複雑にしてしまった場合はご容赦ください。
アプリケーションに対して複数の Tornado インスタンス (サーバーごとに複数のインスタンス、複数のサーバー) を実行しており、アプリケーションで特定のイベントをスケジュールするなど、1 つのインスタンスのみが実行する必要があるいくつかのタスクがあります。このタスクを実行する専用のインスタンスを実行する代わりに、最初に試みたインスタンスがジョブを実行する日和見主義的なアプローチを採用したいと考えています。
私のソリューションの一部は、データベース ベースのロック メカニズム (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
これについて何か考えはありますか?1 回限りのタスクが 1 回だけ実行されるようにするメカニズムも必要なので、ロックは解決策の半分にすぎないことはわかっています。ただし、これは非常によく似た方法で実現できます。問題をよりエレガントに解決するものはありますか?