3

私が開発しているWebアプリケーションは、http要求/応答サイクル中に実行するには長すぎるタスクを実行する必要があります。通常、ユーザーはリクエストを実行し、サーバーはこのリクエストを受け取り、とりわけ、データを生成するためにいくつかのスクリプトを実行します(たとえば、povrayで画像をレンダリングします)。

もちろん、これらのタスクには長い時間がかかる可能性があるため、サーバーは、クライアントに応答を送信する前に、スクリプトの実行が完了するまでハングしないようにする必要があります。したがって、スクリプトの実行を非同期で実行し、クライアントに「リソースはここにありますが、準備ができていません」と指定し、準備ができたときにリソースを取得して表示できるように、おそらくajaxエンドポイントにポーリングするように指示する必要があります。

さて、私の質問はデザインに関連していません(ただし、この点についてのヒントも非常に楽しんでいます)。私の質問は、この問題を解決するためのシステムがすでに存在するので、四角いホイールを再発明しないということです。必要に応じて、プロセスキューマネージャーを使用してタスクを送信し、HTTPエンドポイントを配置して、ajaxクライアントに「保留中」、「中止」、「完了」などのステータスを送信しますが、このタスクのために特別に存在するので、私はほとんどそれを楽しみます。

私はpython+djangoで作業しています。

編集:ここでの主な問題は、サーバーとクライアントがタスクのステータスに関する情報をどのようにネゴシエートして交換する必要があるかではないことに注意してください。

問題は、サーバーが非常に長いタスクの送信とエンキューをどのように処理するかです。つまり、サーバーにLSFでスクリプトを送信させるよりも優れたシステムが必要です。うまくいかないというわけではありませんが、少し多すぎると思います...

編集2:他の答えが得られるかどうかを確認するために賞金を追加しました。pyprocessingを確認しましたが、ジョブの送信を実行して、後の段階でキューに再接続できません。

4

7 に答える 7

4

ここで車輪の再発明を避ける必要があります。

ギアマンをチェックしてください。多くの言語(Pythonを含む)のライブラリがあり、かなり人気があります。djangoをgearmanやajaxの呼び出しに簡単に接続するための、すぐに使える方法があるかどうかはわかりませんが、その部分を自分で行うのは複雑ではありません。

基本的な考え方は、ギアマンジョブサーバー(または複数のジョブサーバー)を実行し、Webリクエストでいくつかの引数('{photo_id:1234}'など)を使用してジョブ('resize_photo'など)をキューに入れることです。これをバックグラウンドタスクとしてキューに入れます。あなたはハンドルを取り戻します。次に、ajaxリクエストは、完了としてマークされるまで、そのハンドル値をポーリングします。

次に、別のPythonプロセスであるワーカー(またはおそらく多数)がこのジョブサーバーに接続し、それ自体を'resize_photo'ジョブに登録し、作業を実行してから、完了としてマークします。

私はまた、その使用法を要約したかなり良い仕事をしているこのブログ投稿を見つけました。

于 2009-12-02T02:22:16.967 に答える
1

2つのアプローチを試すことができます。

  • n間隔ごとにWebサーバーを呼び出し、ジョブIDを通知します。サーバーが処理し、そのタスクの現在の実行に関する情報を返します
  • 長時間実行されるページを実装するには、n間隔ごとにデータを送信します。クライアントの場合、そのHTTPリクエストは「常に」存在し、新しいデータが受信されるたびに新しい情報を収集する必要があります。"loading"

2番目のオプションについては、Cometについて読むことで詳細を学ぶことができます。ASP.NETを使用すると、 System.Web.IHttpAsyncHandlerインターフェイスを実装することで同様のことができます。

于 2009-11-17T12:07:25.967 に答える
1

私はそれを行うシステムを知りませんが、自分のシステムを実装するのはかなり簡単でしょう:

  • jobid、jobparameters、jobresultを使用してデータベーステーブルを作成します
    • jobresultは、結果のピクルスを保持する文字列です
    • jobparametersは、入力引数のピクルスリストです
  • サーバーがジョブの処理を開始すると、サーバーはテーブルに新しい行を作成し、それを処理するために新しいプロセスを起動し、そのプロセスにジョブIDを渡します。
  • タスクハンドラープロセスは、終了時にテーブル内のジョブ結果を更新します
  • Webページ(xmlrpcまたは使用しているもの)には、テーブルのジョブ結果をチェックするメソッド'getResult(jobid)'が含まれています
    • 結果が見つかった場合は、結果を返し、テーブルから行を削除します
    • それ以外の場合は、空のリスト、None、またはジョブがまだ終了していないことを示す希望の戻り値を返します。

世話をするいくつかのエッジケースがあるので、あなたが言うように、既存のフレームワークは明らかに良いでしょう。

于 2009-11-30T07:18:35.453 に答える
1

最初に、いくつかの別個の「ワーカー」サービスが必要です。これは、電源投入時に別個に開始され、UNIXソケット(高速)やデータベース(単純)などのローカルIPCを介してhttp-requestハンドラーと通信します。

リクエストの処理中に、cgiはワーカーの状態またはその他のデータから要求し、クライアントに再生します。

于 2009-12-01T11:23:10.950 に答える
0

202 HTTPコードで応答することにより、リソースが「処理中」であることを通知できます。クライアント側は、完成したリソースを取得するために後で再試行する必要があります。場合によっては、リクエストとレスポンスを照合するために「リクエストID」を発行する必要があります。

または、「箱から出してすぐに」ニーズを満たす可能性のある既存のCOMETライブラリを確認することもできます。ただし、現在のDjangoのデザインに一致するものがあるかどうかはわかりません。

于 2009-11-17T12:23:54.653 に答える
0

おそらく、使用しているpython / djangoソリューションには適していませんが、このような場合はMicrosoftメッセージキューを使用します。基本的にはこのように動作します

  1. Webサイトは、データベースの行を「処理中」のステータスで更新します
  2. WebサイトはMSMQにメッセージを送信します(これはノンブロッキング呼び出しであるため、すぐにWebサイトに制御を戻します)
  3. Windowsサービス(実際にはどのプログラムでもかまいません)はMSMQを「監視」しており、メッセージを受け取ります
  4. Windowsサービスは、データベース行を「終了」ステータスで更新します。

それはとにかくそれの要点です。それは私たちにとって非常に信頼性が高く、拡張と管理が非常に簡単です。

-al

于 2009-12-02T02:39:57.610 に答える
0

Pythonとdjangoのもう1つの優れたオプションは、Celeryです

また、 Celeryがニーズに対して重すぎると思われる場合は、単純な分散タスクキューを確認することをお勧めします。

于 2012-02-18T15:18:34.543 に答える