私の Django Web アプリには、レート制限された API のクライアントであり、サーバー スレッドからその API へのすべての要求を処理するワーカー プログラムがあります。データベースを使用してタスク キューを格納します。タスクは大量に発生する場合もあれば、まったく発生しない場合もあります。イベントループを使用してキューをポーリングし、レート制限を超えた場合に備えてタスク間の遅延を管理しています (制限は動的です)。これはすべて正常に機能しますが、他にやりたいことは、キューが空になった場合にワーカーがデータベースへのアクセスを停止する方法と、Django アプリがキューがなくなったことをワーカーに通知する方法を用意することです。再び乾かします。
概略的には、疑似 Python では次のようになります。
state = NORMAL
delay_time = NORMAL_DELAY
while True:
sleep(delay_time)
if state == DORMANT:
continue
task = get_next_task() # hits database
if task is None:
state = DORMANT
delay_time = NORMAL_TIME
try:
execute(task)
except RateExceeded:
delay_time = backoff(delay_time)
else:
delay_time = NORMAL_DELAY
# Triggered by web layer
def asynchronous_event():
state = NORMAL
そして、状態をNORMALに戻すことができるWebレイヤーからトリガーされる非同期イベント(実行中に実行されるsleep
)、または不要なループDBクエリを追加しない他の軽量チェックが必要です。
単一マシンのセットアップでは、シグナルを使用することもできますが、これは明らかに複数マシンのセットアップでは機能しません。この 1 つのシグナルのためだけに別のメッセージ キュー サーバーを実行する必要がないようにしています。ネットワークベースのソリューションが機能する場合に備えて、私は Dotcloud でホストされています。理想的には、シグナル ハンドラーとしての実装の容易さにおいて多かれ少なかれ同等のものです。ZeroRPC を調べましたが、イベント ループに組み込む方法がわかりません。
何か案は?
編集
この問題を解決するために ZeroMQ を調べていますが、助けが必要です。注意が必要なのは、複数の Web サーバー インスタンスが同時に存在することです。再デプロイ時には、1 つのワーカーから後続のワーカーにスムーズに移行する必要があります。私の用語はおそらく正しくないので、ご容赦ください。最善の方法は、各ワーカーをメールボックスとしてアドレスに非同期的にバインドし、メインループでチェックして休眠モードから復帰させることです。 . 各ワーカーは、IP のデータベースにレコードを作成し、作成日のタイムスタンプが付けられます。リクエストを送信すると、Web サーバーはすべてのワーカーにメッセージを発行します。ワーカーは、メッセージを受信すると、作成日が最新のワーカーであるかどうかを確認します。作成日が最新のワーカーである場合はメッセージを処理し、そうでない場合は自分自身を終了します。
これは大変なことのように思えますが、アプリケーションの他の場所でこのパラダイムを使用する可能性が高いため、これを正しく処理したいと考えています。