18

celery/rabbitmq 展開の単一障害点である celerybeat を回避するための推奨ソリューションを探しています。ウェブを検索しても、これまでのところ意味のあるものは見つかりませんでした。

私の場合、1 日 1 回、時間指定されたスケジューラーが、半日以上実行できる一連のジョブを開始します。celerybeat インスタンスは 1 つしか存在できないため、それまたはそれが実行されているサーバーに何かが発生した場合、重要なジョブは実行されません。

信頼できる(クラスタ化されたなどの)スケジューラを必要とするのは私だけではないので、これに対する有効な解決策がすでにあることを願っています。必要がないのであれば、ある種のデータベースを利用したスケジューラに頼りたくありません。

4

1 に答える 1

7

これについて、セロリの github リポジトリに未解決の問題があります。彼らがそれに取り組んでいるかどうかはわかりません。

回避策として、特定の PeriodicTask の 1 つのインスタンスのみが一度に実行されるように、タスクのロックを追加できます。

何かのようなもの:

if not cache.add('My-unique-lock-name', True, timeout=lock_timeout):
    return

ロックのタイムアウトを把握するのは、かなりトリッキーです。異なる celerybeats が異なる時間にそれらを実行しようとする場合、0.9 * task run_every 秒を使用しています。わずかなマージンを残すためだけに 0.9 を使用します (たとえば、セロリがスケジュールより少し遅れている場合、スケジュールどおりであり、ロックが引き続きアクティブになる可能性があります)。

その後、すべてのマシンで celerybeat インスタンスを使用できます。各タスクはすべての celerybeat インスタンスのキューに入れられますが、実行を終了するのはそのうちの 1 つのタスクだけです。

タスクはこの方法でも run_every を尊重します - 最悪のシナリオ: タスクは 0.9*run_every の速度で実行されます。

この場合の 1 つの問題: タスクがキューに入れられたが、スケジュールされた時間に処理されなかった場合 (たとえば、キュ​​ー プロセッサが使用できないため)、ロックが間違った時間に設定される可能性があり、次の 1 つのタスクが実行されない可能性があります。これを回避するには、タスクが時間どおりかどうかにかかわらず、何らかの検出メカニズムが必要になります。

それでも、本番環境で使用する場合、これは一般的な状況ではありません。

別の解決策は、celerybeat Scheduler をサブクラス化し、その tick メソッドをオーバーライドすることです。次に、ティックごとに、タスクを処理する前にロックを追加します。これにより、同じ定期的なタスクを持つ celerybeats のみが、同じタスクを複数回キューに入れないようになります。ティックごとに 1 つの celerybeat (競合状態に勝った人) だけがタスクをキューに入れます。ある celerybeat でダウンし、次のティックで別の 1 つがレースに勝ちます。

もちろん、これは最初のソリューションと組み合わせて使用​​ できます。

もちろん、これを機能させるには、すべてのサーバーでキャッシュ バックエンドを複製および/または共有する必要があります。

これは古い質問ですが、誰かの役に立てば幸いです。

于 2012-10-18T15:28:19.560 に答える