8

フロントエンドでTomcatWebサーバーと標準のJavaScriptを使用してサーバー側のプッシュ(comet)を実行できるように、長いポーリング接続を実装しました。接続を維持するために、最後の要求が完了する/失敗するとすぐに新しい要求を開始する単純なキープアライブループがあります。

ほとんどの場合、この接続は完全に正常に機能し、期待どおりに機能し続けます。しかし、ユーザーのインターネット接続が切断され(VPNから切断したり、イーサネットのプラグを抜いたりするなど)、サーバーへの保留中のXMLHttpRequestがある場合、失敗の兆候が見られないことに気付きました。このため、接続はサイレントに切断され、接続をテストするための要求をサーバーに絶えず送信しない限り、接続が発生したことを知ることができません(これは長いポーリングを使用する目的を損なうようです)。

このサイレントデスが終了したときにChromeに表示されるリクエストオブジェクトは次のとおりです。

request: XMLHttpRequest
    onabort: function ()
    onerror: function ()
    onload: null
    onloadend: null
    onloadstart: null
    onprogress: null
    onreadystatechange: function ()
    readyState: 1
    response: ""
    responseText: ""
    responseType: ""
    responseXML: null
    status: [Exception: DOMException]
    statusText: [Exception: DOMException]
    upload: XMLHttpRequestUpload
    withCredentials: false

3つのリスナー(onabort、onerror、onreadystatechange)が起動した場合にメッセージを警告するように設定していますが、サーバーへの接続を切断しても何も表示されません。リクエストの作成方法は次のとおりです。

var request = new XMLHttpRequest();

//url is just the url to my servlet to handle this
request.open("GET", url, true);

//handlestatechange is just my standard handling code 
//that I've put an alert at the top of
request.onreadystatechange = handleStateChange;

request.onerror = function()
{
    alert("We encountered an error");
}

request.onabort = function()
{
    alert("I've had an abortion");
}

request.send(null);

これはかなり標準的な状況のようですが、この種の切断から長いポーリング接続を回復できるようにする方法についての会話は見たことがありません。

私は何か間違ったことをしていますか?この問題を回避する、長いポーリング/彗星を実行するための他のより標準的なアプローチはありますか?

これに関する助けをいただければ幸いです、ありがとう

4

2 に答える 2

2

これを処理する最善の方法は、ロングポールリクエストの期間を一定の時間に制限しT(たとえば、60秒は不合理な値ではありません)、クライアントでタイムアウトを使用して停止状態を検出することです。理想的にはXHRtimeoutプロパティを使用してこれを行いますが、W3C仕様に含まれているにもかかわらず、x-browserはサポートされていません。したがって、とを使用して独自のサポートを実装する必要がsetTimeoutありますxhr.abort()

クライアントは、T秒以内に応答がない場合、接続が停止していると見なすことができ、現在の要求を中止して再接続を試みることが適切です。

これはかなりうまく機能しますが、クライアントの接続が停止したとき(最大T秒)の検出にある程度の遅延があることを意味します。長い間、私はこれについてやるべきことがたくさんあることを知りません。より良いソリューションが本当に必要な場合は、ハートビートメッセージまたはWebSocketを送り返すストリーミングコメット接続を確認することをお勧めします。

それが簡単な答えです。残念ながら、これはあらゆる種類の奇妙なエッジケースで重要な問題であることが判明しました。たとえば、接続タイムアウトのあるプロキシサーバーや、ユーザーのコンピューターでデフォルトのTCPタイムアウトを変更するさまざまな方法を気にする場合と気にしない場合があります。これが、この醜さの多くを隠すSocket.IOのようなフレームワークが出現するのを見た理由です。

PSを介して一部のブラウザでオンライン状態を監視できることはおそらく注目に値しますがnavigator.onLine、サポートが不十分です。それが実際に正しく動作する唯一のブラウザはChromeです。それが実際にあなたに伝える唯一のことは、ユーザーが何らかの理由でオフラインであることがわかっているかどうかです。彼らが正常に機能していることをあなたに伝えることはできません。

于 2013-01-08T14:34:52.387 に答える
0

解決策は、TCPキープアライブを有効にすることです。これは、到達可能性が失われたときに接続を閉じるためのTCPのメカニズムです。アプリケーションを変更する必要はありません。O/Sまたはサーバーアプリケーションの両方でキープアライブを有効にできます。

于 2018-08-28T13:20:42.003 に答える