10

ユーザーがブラウザーを介して何らかの要求を Python Web アプリケーションに送信する (オープン ソース) Web アプリケーションを実装したいと思います。要求データは、ある種の負荷の高いコンピューティング ジョブを定義して送信するために使用されます。コンピューティング ジョブは、「ワーカー バックエンド」(これも Python) にアウトソーシングされます。ジョブの処理中、ジョブは時間の経過とともにさまざまな段階を経ます (理想的には、中間状態の「送信済み」から「終了」まで)。私が達成したいのは、現在のジョブの状態をリアルタイムでユーザーに表示することです。これは、ワーカー バックエンドがジョブの状態を Web アプリケーションに伝える必要があることを意味します。次に、Web アプリケーションはユーザーのブラウザーに情報をプッシュする必要があります。基本的なアイデアを図式的に説明する写真を用意しました。 回路図の問題の説明

赤い丸の中の数字は、出来事の時系列を示しています。「Web アプリ」と「ワーカー バックエンド」はまだ設計中です。では、テクノロジーに関する決定をお手伝いいただけると幸いです。

私の質問、具体的には:

  1. Web アプリとワーカー バックエンドの間にどのメッセージング テクノロジを適用する必要がありますか? ワーカー バックエンドが特定のジョブに関するシグナル (何らかのメッセージ) を送信すると、Web アプリケーションで何らかのイベントをトリガーする必要があります。したがって、最初にジョブの送信を要求したクライアントに関連付けられた何らかのコールバックが必要です。ここには、ワーカー バックエンドがパブリッシュし、Web アプリがサブスクライブする pub/sub メカニズムが必要だと思います。Web アプリは、メッセージを受信すると、クライアントにステータス更新を送信することで対応します。ワーカー バックエンドをスケーラブルにし、Web アプリケーションから強力に切り離したいと考えています。したがって、このタスクには Redis または ZeroMQ を使用することを考えていました。どう思いますか?私の全体的なアプローチは少し複雑すぎますか?

  2. ブラウザーに情報をプッシュするには、どのテクノロジーを使用すればよいですか? 完璧主義なので、リアルタイムで更新したいと思います。高頻度でポーリングしたくありません。ワーカー バックエンドがメッセージを送信したときに、クライアントにすぐにプッシュしたい :-)。また、最大限のブラウザ サポートは必要ありません。まず第一に、このプロジェクトは多かれ少なかれ私自身の技術デモです。HTML5 サーバー送信イベント/Websocket を使用する必要がありますか? それとも別の方法をお勧めしますか?

事前にお勧めいただきありがとうございます。

4

3 に答える 3

4

オプションは WebSocket を使用することです。その道を行く場合は、Python (Twisted) 用のクライアントとサーバー、および WebSocket 上の RPC+PubSub プロトコル (Python、JavaScript、および Android 用のライブラリを含む) を含むAutobahnをチェックしてみてください。RPC+PubSub サブスクリプションを使用すると、重要な作業が安全になり、ニーズに合う可能性があります (ジョブの送信 => RPC、ジョブの作業の更新 => PubSub)。

AutobahnPython は Twisted 上で実行され、Flask (または他の WSGI ベースの Web フレームワーク) を実行できるようにする WSGI コンテナーとしても機能します。1 つのポート/サーバーですべてを実行できます。後者については、GitHub Autobahn リポジトリに例があります。

免責事項: 私は Autobahn と WAMP の原著者であり Tavendo で働いています。

詳細: あなたのワーカーは、CPU を集中的に使用したり、ブロッキングを行ったりしていると思います。

まず、ワーカーは純粋な Python ですか、それとも外部プログラムですか?

後者の場合、メインの Twisted スレッドから stdio パイプを介して (ノンブロッキング方式で) 通信する Twisted プロセス プロトコル インスタンスを使用できます。前者の場合は、Twisted バックグラウンド スレッド プールを使用し、Twisted deferToThread を使用できます ( http://twistedmatrix.com/documents/current/core/howto/threading.htmlを参照)。

Autobahn はメインの Twisted リアクター スレッドで実行されます。ワーカーもそうする場合 (前のコメントを参照)、WebSocket/WAMP ファクトリ/プロトコル インスタンスでメソッドを直接呼び出すことができます。そうでない場合 (ワーカーがバックグラウンド スレッドで実行されている場合)、callFromThread を介してこれらのメソッドを呼び出す必要があります。

WAMP を使用する場合、主なことは、各ワーカーへの WampServerFactory の参照を取得することです。その後、ワーカーは、適切なファクトリ メソッドを呼び出すことで、PubSub イベントをすべてのサブスクライバーにディスパッチできます。

于 2012-10-04T20:59:25.607 に答える
3

あなたはPython Webアプリケーションについて話しているので、以下を調べることをお勧めします:

Web アプリとワーカー バックエンドの間にどのメッセージング テクノロジを適用する必要がありますか?

Celery - クライアントに表示する必要がある結果を返す小さなタスクにジョブを分割します

ブラウザーに情報をプッシュするには、どのテクノロジーを使用すればよいですか?

NodeJS種類のサーバー側JS フレームワークまたはPython Web フレームワーク用の Web ソケット ライブラリのソケット IO

Python にあまり縛られていない場合は、Meteorをチェックしてください

このスレッドに基づいて、サーバーから Web クライアントへの進行状況をリアルタイムで更新する他の方法には、進行状況を redis データベースに書き込むか、セロリのサブタスクからの非同期結果に基づいてSTOMP プロトコルを使用してOribited / Morbid (どちらもTwistedに基づく) を使用することが含まれます。

于 2012-10-04T19:13:17.150 に答える
3

役に立つように、Web アプリケーションにはデータベースが必要です。そのデータベースに、これらのジョブ専用のテーブルを作成します。ジョブごとに「状態」があります。

これにより、ジョブを開始するリクエストを送信してバックエンド ワーカーに渡すことができるため、システムが簡素化されます (zmq は、この IMO の優れたソリューションです)。バックエンドに python を使用しているため、ワーカー ジョブにデータベース内の現在の作業ジョブを更新させるか、データベース内のフィールドを更新するだけのジョブを持つ別の「アップデーター」を用意するのは非常に簡単です (ロジックを分離したままにします)。より良い解決策になり、多くの更新を行っている場合は、複数の「アップデーター」を起動できる可能性があります)

次に、フロントエンドについては、サーバーをポーリングしたくないので、「長いポーリング」を行います。基本的に行っているのはサーバーのポーリングですが、関心のあるデータに変更があるまでサーバーは実際に「応答」しません。変更があるとすぐに、要求に応答します。フロントエンドでは、JS が最新の更新を受信するとすぐに接続を再確立します。このソリューションは、クロスブラウザーでもある JS フレームワークを使用している限り、クロスブラウザーに準拠しています (jQuery をお勧めします)。


Web アプリケーション データベースのポーリングを排除するには、次の手順を実行します。

最初のリクエストを Web アプリへの長いポーリング リクエストにします。Web アプリは zmq メッセージをバックエンドに送信し (おそらく REQ/REP ソケットで行う必要があります)、待機します。zmq バックエンドから状態変化のメッセージを受け取るまで待機します。状態の変化を受け取ると、その変化をフロントエンドに応答します。この時点で、フロントエンドは新しいロング ポール リクエストを送信し (このジョブの現在の ID を ID として使用)、Web アプリはバックエンドに再接続し、別の状態変化を待ちます。これを機能させる秘訣は、ZMQ を使用することです。ZMQ_IDENTITYソケットが最初に作成されたとき (最初の要求)。これにより、Web アプリが同じバックエンド ソケットに再接続し、新しい更新を取得できるようになります。バックエンドに送信する新しい更新がある場合、Web アプリに通知し、Web アプリは状態の変化でロング ポール リクエストに応答します。このようにpolling、バックエンド データベースはなく、すべてがバックエンド ワーカーからのイベント ドリブンです。

フロントエンドがなくなった場合 (ページを切り替えたり、ブラウザを閉じたり) した場合に、バックエンド ソケットが適切に閉じられるように、ある種のウォッチドッグをセットアップします。状態が変化したときに無期限にブロックする必要はありません。

于 2012-10-05T12:19:19.683 に答える