私は.Netのバックグラウンドから来て、Pythonに比較的慣れていません。
短いバージョン: アプリケーション全体のシングルトンまたはその他のメカニズムを作成して、複数のスレッド/プロセスが相互に通信できるようにするにはどうすればよいですか?
たぶん私は甘やかされていますが、.NetではApp_Start
、「アプリケーションレベル」で何かを作成するだけです。python/uwsgiで同じことを行うにはどうすればよいですか?
長いバージョン:
Django を使用して記述された安らかな API があります。
一部の呼び出しでは、前処理を行ってから、長時間実行される操作を実行するバックエンド システムに渡す必要があります。
今の流れはこんな感じ…
- 指定された条件に一致するすべてのドキュメントを処理する要求を受け取る
- API は、これらの条件に一致するドキュメントを決定します (100,000 のオーダーで、15 ~ 20 秒かかります)。
- API は、このバッチ リクエストの uuid を生成します
- API は、バッチ ID を参照して、これらのドキュメントごとにバックエンド キューにメッセージを発行します。
- API は「完了」メッセージを別のキューでリッスンし、各バッチ ID の成功/失敗をカウントします (~1-15 分)
- 処理が行われている間、UI は特定のバッチ ID の更新を要求できます
待機スピンループにあるため、ページを提供するために使用されるスレッドとは異なるスレッドを使用して、応答キューをリッスンする必要があります...
while True:
self.channel.wait()
QueueManager
シングルトンであるa への参照を取得することで、これを処理していました。マネージャーは最初の要求を開始し、バッチ ID を記録してから、2 番目のスレッドでキューを監視し、ローカルの状態を更新します。
状態を長期的に保存することは実際には気にしません。メッセージがキューにある場合、処理はバックエンドによって行われ、状態の監視はユーザーが進行中であることを示すだけです。ブラウズすると、ステータスにもアクセスできなくなります (バッチ ID は JS のメモリ内に保存されます)。
これにはいくつかの利点がありました。情報の同期 (および関連するクリーンアップ) にデータベースを使用する必要がなくなりました。単一のスレッドをメッセージ コンシューマとして使用でき、同時実行の問題について心配する必要はありませんでした。これは、メッセージを収集したり、ローカルの状態を更新したりするスレッドが 1 つだけであるためです。
それで...今度はuwsgiを使用して実行します。大きな問題が見つかりました。プロセス数を 1 に設定すると、シングルトンは期待どおりに動作しますが、API がデータを処理している 15 ~ 20 秒の間、すべてのリクエストがブロックされます。明らかにそれは受け入れられません。逆に、複数のワーカーをスピンアップすると、それぞれに独自のシングルトンと独自のメッセージ リスナーがあるため、パブリッシャーとコンシューマーが同じプロセスである場合はほぼランダムになります。たとえそうであったとしても、ステータス更新のリクエストはおそらく同じプロセスにはなりません。
複数のワーカー間で状態情報を交換するにはどうすればよいですか? 複数のワーカーの代わりに複数のスレッドを使用する方法はありますか?
本当に必要なようです:
- n スレッド、それぞれがリクエストを処理
- キューでリッスンしている 1 つのスレッド
- それらの間で通信するためのメモリ内の方法
私はすでに持っていますが--enable-threads
、それは私が生成した新しいスレッドにのみ適用されるようです(デフォルトで有効にならない理由はわかりません)