1

tl;dr : jQuery の ajax 関数は、タイムアウトした http 要求を閉じないようです。そのため、各ロング ポーリング リクエストごとに開かれた各ソケットは決して閉じず、サーバーは開いているソケットの数が原因で最終的に接続を拒否します。 これらの接続がタイムアウトしたら閉じることは可能ですか? そうでない場合、ロングポーリングへのアプローチのどこが間違っているのでしょうか?

注:これはおそらく予期された動作であることは認識していますが、すべての可動部分を追跡し、問題の誤解を特定するのに悪夢を見ています。あなたが提供できるガイダンス/明確さは大歓迎です。

lighttpd、cppcms (C++ Web フレームワーク)、および jQuery を使用して、プッシュ ベースの通知を示す簡単なアプリケーションを開発しました。クライアントはこれを行います:

function listen(){
  $.ajax({
    url: "/push_test",
    type: "POST",
    timeout: 3000, // 3 seconds
    data: {
      will_leak: true
    },
    success: function(r){
      console.log("server responded: " r);
    },
    error: function(xhr, st, e){
      console.log("push_test error");
      console.dir(xhr);
      console.log("status: " + st);
      console.log("error: " + e);
    },
    complete: function(){
      //listen();
    }
  });
}

そして、サーバーは次のようなことを行います (Python Flask マイクロフレームワークで同様のテストを行い、次の cppcms 実装と同じ結果が得られました)。

void push_test()
{
    if(request().post("will_leak")){
        std::this_thread::sleep_for(std::chrono::seconds(5)); // Note client timeout of 3 seconds.
    }
    response().set_plain_text_header();
    response().out() << "If you see this on the client, we're all gucci";
    // Hint: if will_leak was true, you never see the above message.
}

ajax 呼び出しがタイムアウトしたときに Firefox の開発者ツールのネットワーク タブを調べると、HTTP 要求が応答またはステータス コードを返さなかったことが示されますが、コンソールは ajax 呼び出しの「エラー」コールバックでタイムアウトの失敗を示します。Chrome の開発者ツールのネットワーク タブを同様に調べると、タイムアウトになったときにリクエストが「キャンセル」されたことがわかります。サーバーで開いているソケット ファイル記述子を調べると、タイムアウトしたソケットが CLOSE_WAIT 状態にあり、サーバーを停止して再度起動するまでそのままの状態が続くことがわかります。

時間を割いてすべてをお読みいただきありがとうございます。問題を特定するためにさらに情報が必要な場合はお知らせください。その間も掘り続けます。

4

0 に答える 0