web-dev-qa-db-ja.com

クライアントがCGIから切断されたことを検出できますか?

データの送信を開始するのにかなり長い時間がかかる、かなりリソースを消費するCGIがあります。せっかちな人が数回リロードし、それがCGIの追加の実行をトリガーしてロードする場合や、クライアントがタイムアウトして接続を切断したが、CGIが実行し続ける場合がかなりあります。

これがいつ起こったかを検出する良い方法はありますか? CGI自体の中にある必要はありませんが(そうでない場合はおそらくより良いです-私が制御できない別のプログラムに渡されます)、頻繁に実行されるcronジョブである可能性があります刈り取るためのデッドコネクションを探す。

私は現在Apacheを使用していますが、これは非常に問題であるため、他のWebサーバーに対処するためのプロビジョニング(または問題を監視させる方法)があれば、他のWebサーバーを実行してもかまいません。

4
Joe H.

通常、ユーザーへの書き戻しを開始するまで、接続の切断を検出することはできません。それ以外の場合、プロセスはユーザー側からの接続の中止に気付かずに作業を続行します。 この投稿 はPHPについて話していても関連しています。コンセプトは同じでなければなりません。

あなたが試すことができる可能性のあることがあります:

  1. 時間のかかる作業をバックグラウンドで実行します。ユーザーがCGIを要求するときは、通常のブロッキング呼び出しとしてタスクを実行しないでください。ユーザーに何かを返すだけで、リクエストが処理中であることがわかります。もちろん、ビューを更新する方法を見つけるか、リクエストIDまたはIPを使用してジョブのステータスを確認するための別のページを提供する必要があります。
  2. できるだけ早くデータをクライアントに送り返し、送信に失敗した場合は終了します(接続が切断されたことを示します)。たとえば、ジョブの進行状況を数秒または数分ごとに送信できます。

現在実行中のジョブをデータベースに保存する場合は、リクエストIDやクライアントIPアドレスを保存できます。したがって、同じリソースへの重複するリクエストを検出して無視し、ユーザーに「リクエストは処理中です」と伝えることができます。

5
Khaled

古い質問ですが、同じ問題が発生し、接続が安定しているかどうかの確認を解決しました。

私の場合、サーバー上で1つのbashスクリプトを実行しています。env変数はmod_cgiによってエクスポートされます。このソリューションは、CGIで実行されているすべてのプログラム/スクリプトで機能すると思います。

ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
     # Client closed browser/connection
fi
2
Cycne

警告:この情報は廃止されている可能性があります。最後の段落を参照してください。

同じ問題が発生し、 nph (解析ヘッダーなし)CGIスクリプトで解決したことを覚えています。

通常、Apacheはスクリプトからすべてのヘッダーを収集し、ヘッダーの読み取りが終了したら、提供しなかったいくつかの標準ヘッダーでそれらを修正します。つまり、ヘッダーを終了しない限り、Apacheはクライアントに何も送信しません。

Nphスクリプトでは、すべてのヘッダーを提供する必要がありますが、Apacheはそれらをすぐにクライアントに送信し、クライアントが切断されるとCGIスクリプトにSIGPIPEを送信します。したがって、クライアントでのタイムアウトを防ぐために、数秒ごとに_X-Slowly-Counting-Part-nnn: yes_ヘッダーを送信すると、クライアントが接続を切断した場合に通知が届きます。

これでも問題が残りますが、最初にHTTPステータスを送信する必要がありますが、「Content-Length:0」または「Content-Length:1」を送信し、コンテンツを送信せずに接続を閉じると、ファイルダウンローダーはネットワークエラーを想定し、それに応じて動作する必要があります

おそらく、他のプログラムの出力をプロセスにパイプする必要がありますが、少なくともLinuxを使用していて、sendfile(2)システムコールを使用している場合、これはパフォーマンスに大きな影響を与えることはありません。

これらすべての問題は、少なくとも10年前、おそらくApache 1.3で使用したことであり、_Apache cgi nph_をグーグルで検索しても何も役に立ちませんでした。ですから、その間にnph機能が削除されたのかもしれませんが、そうではないかもしれませんが、私はそれほど難しく見えなかったことを認めます。