応答時間が長いリクエストのパターンは?


7

現在、自社開発のpython「ウェブサーバー」を維持しています。この場合、一部のリクエストに対する応答の生成には、主に重い計算が原因で非常に長い時間がかかる可能性があります。これらのリクエストは、基本的に非常に長いタイムアウト(数分から数十分と考えてください)を持つ投稿です。

このアーキテクチャの1つの問題は、そのようなリクエストをキャンセルする必要がある場合があることです。たとえば、ユーザーがリクエストの設定中にミスに気付きました。現在、キャンセルは別のリクエストであり、長時間実行されているリクエストをキャンセルします-しかし、多くのギャップがあります。

現在、Webサーバーの自作の廃止を廃止し、賢明な何かに切り替えることを計画しています-たとえば、Wfastcgiを使用してIIS内で実行されているFlask。政治的な理由により、IISが設定されているため、gunicornのようなものに切り替えることはできません。

(w)fastcgiによって実行されるプロセスを強制終了する方法は誰にもわからないため、すべての開発はそれで行き詰まりました。その懸念は単にfastcgi仕様の一部ではありません。

私の考えでは、それを組み込んだものを構築する試みは間違いです。サーバーがバックグラウンドサーバー(フラスコ+セロリ?)にそのような計算集中型のタスクをオフロードし、そのためのフロントエンドポーリングをオフロードするソリューションを好みます。

残念ながら、古いソリューションは長期間使用されていたため、一部の開発者はすべてのコストで動作を維持したいと考えていました。

Webサーバーの男ではないので、このような問題の賢明な解決策がどのようなものになるか、いくつかのヒントやパターンを教えてください。

回答:


8

あなたが示唆していることはまったく正しい。

非同期でなければなりません。

リクエストを投稿すると、リクエストに一意のIDが付与されます。ポーリングできるいくつかのストアで、この一意のIDの完了を投稿します。

リクエストをキャンセルする必要がある場合は、同じIDを使用したキャンセルリクエストを投稿する必要があります。

また、この計算が実行されているバックエンド、たとえばスレッド(Javaスタイル)の実行インターフェースでは、キャンセルポストがリクエストされているかどうかをチェックすることにより、プロセスがキャンセルされたかどうかを数秒ごとに確認できます。存在する場合、スレッドは終了する必要があります。これはきれいな出口です。スレッドへの割り込みを使用することもできます。


私見この解決策は、Httpに非常によく適合する「ステートレス」アプローチに最もよく適合するものです。計算を行う動作と要求/応答通信を分離します。このパターンでは、要求/応答通信は次のような会話になります。..まだ機能しています..キャンセルしてください..わかりましたキャンセルします..どのように進みますか?..計算がキャンセルされました..開始してください...(待機)..どのように乗りますか?..ここで完了した計算が結果です。
ロバート

2

wsgiを調べてマルチスレッドを使用することをお勧めします。スレッド内の各リクエストを管理し、スレッドにタイムアウトを実装できます。また、スレッドを管理し、リクエストをより簡単にキャンセルできる必要があります。


1

単純なHTTPポストで現在直面している問題は、そのプロトコルでは解決できません。HTTPは厳密なクライアント/サーバーで非同期に動作するため、サーバー側の通知やネイティブキャンセルはありません。また、インターネットネットワークのタイムアウトのために回答が失われるという問題にも直面します。私は別の現代的なアプローチを提案します。免責事項:ブラウザのサポートが90%未満

情報の流れを逆にしてWebSocketを使用することをお勧めします。タスクが完了したら、ユーザーに通知し、サーバーからクライアントに通知をプッシュする必要があります。

タスクが投稿されたら、またはより正確には、投稿の代わりに、WebSocketを開きます(好きなサーバーテクノロジー、トルネード、Gevent、Python WebSocketなどを使用します)。サーバーのwebsocket openイベントにタスクスレッドを関連付けます。クライアントが終了すると、クライアントはcloseイベントをwebsocketハンドラーに送信するので、それに関連付けられているスレッドを終了できます。それ以外の場合、タスクが正常に終了すると、サーバーはクライアントにデータを送信してWebSocketを閉じることができます。また、WebSocketが1分以上アクティブでない場合は閉じるため、サーバーに30秒ごとにpingを実行する必要があります。

これを適用すると、実際の双方向チャネルがあるため、ギャップの問題を解決しながら、クライアント側のポーリングよりも高速でクリーンになります。セッション、進行状況のpingなど、タスクスキーマに追加のサービスを実装できることに注意してください。


0

タスクの実行にそれだけの時間が必要な場合は、その要求に対してそれを行わないでください。それをキューに入れ、作業を行う別のプロセスを作成します。

作業が完了したら、「操作x」が完了したことをユーザーに通知します。その間、「作業は約x分で完了します」というメッセージが表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.