8

Spring-MVC Web アプリにロング ポーリングを実装しようとしていますが、4 ~ 5 回の AJAX 要求が続くと、ブラウザーやその他の要求がフリーズします。ここで何が起こっているのかがわかりません。

コントローラーメソッド:(サーバー側):-

@Asynchronous
    @RequestMapping("/notify")
    public @ResponseBody
    Events notifyEvent(HttpServletRequest request) {
        Events events = null;
        try {
            events = (Events) request.getSession(false).getServletContext().getAttribute("events");
            System.out.println("Request Came from" + ((com.hcdc.coedp.safe.domain.User) request.getSession(false).getAttribute(Constants.KEY_LOGGED_IN_USER)).getLoginId());
            if (!events.getTypeOfEvents().isEmpty()) {
                System.out.println("Removing older entries");
                events.getTypeOfEvents().clear();
            }
            while (!events.isHappend()) {
                //Waiting for event to happen.
            }
            events = Events.getInstance();
            events.setHappend(false);
            request.getSession(false).getServletContext().setAttribute("events", events);

        }catch (Exception e) {
            e.printStackTrace();
        }
        return events;
    }

ロング ポーリング スクリプト (クライアント側):-

$(document).ready(function() {
                    $.ajaxSetup({
                        async:true//set a global ajax requests as asynchronus
                    });
                     alert('Handler for .onload() called.');
                    waitForMsg();

                });
                function waitForMsg(){

                    xhr=  $.ajax({
                        type: "POST",
                        url: '<%=request.getContextPath()%>/notification/notify',

                        async: true, /* If set to non-async, browser shows page as "Loading.."*/
                        cache: false,
                        timeout:50000, /* Timeout in ms */
                        global:false,
                        success: function(data){ /* called when request to notifier completes */
                          /* Doing smthing with response **/
                            setTimeout(
                            waitForMsg, /* Request next message */
                            1000 /* ..after 1 seconds */
                        );
                        },
                        error: function(XMLHttpRequest, textStatus, errorThrown){
                            addmsg("error", textStatus + " (" + errorThrown + ")");
                            setTimeout(
                            waitForMsg, /* Try again after.. */
                            15000); /* milliseconds (15seconds) */
                        }
                    });
                };

アップデート:

function updateFeed(event, data) {
                var f=eval(data);
                alert(f.typeOfEvents.length);
            }

            function catchAll(event, data, type) {
                console.log(data);
                alert("error");
                console.log(type);
            }

            $.comet.connect('<%=request.getContextPath()%>/notification/notify');
            $(document).bind('feed.comet', updateFeed);
            $(document).bind('.comet', catchAll);

どちらの警告ボックスもポップアップしません..:(

4

7 に答える 7

10

セッション ファイルのロックが発生したようです

PHPの場合

session_write_close()セッション値が不要な場合に使用します

于 2013-12-14T06:58:05.127 に答える
5

ブラウザ コードに空の while ループがあるようです。これは、イベントを待機するための非常に CPU を集中的に使用する方法です。

イベントが発生しない場合、クライアントは希望する 50 秒のタイムアウト後にリクエストを強制終了します。しかし、サーバー スレッドも強制終了されるのか、それとも (イベントがない限り) 永遠に「間」続くのかはわかりません。次のリクエストは、while ループでハングする 2 番目のサーバー スレッドを開始します。おそらく、空の while ループの量はサーバーにとって過剰であり、それ以上のリクエストの受け入れを停止します。したがって、いくつかのリクエスト(それぞれが無限のサーバースレッドをトリガーした)の後、クライアントは新しいリクエストを永遠に待ちます..サーバーで処理できないためです。

ps: 成功したら、1 秒待つようにコメントしましたが、タイムアウトを 10000 (10 秒) に設定しました

于 2012-10-13T12:42:35.167 に答える
2

私は同様の問題に遭遇しました、私のブラウザはどういうわけかAJAXリクエストで立ち往生していました。ヒント:代わりに、waitForMsg()を直接使用して、 setTimeout( "waitForMsg()"、10)を試してください。

于 2012-10-12T09:26:54.337 に答える
2

参考までに、ここにあなたを助けるかもしれないプロジェクトがあります:https ://github.com/SeanOC/jquery.comet

一般に、長いポーリングへの適切なフォールバックを備えたクライアント/サーバーで利用可能な場合、WebソケットをサポートできるJavaScriptコメットAPIを検索します。APIはすべての厄介な詳細を処理する必要があり、アプリケーションに集中できるようになります。

このトピックに関する古いdojoの記事へのリンクは次のとおりです:http://dojotoolkit.org/features/1.6/dojo-websocket

幸運を。

于 2012-10-12T19:14:39.970 に答える
2

jQuery deferred を使用して動作を書き直すことができます。

function setShortTimeout() {
    setTimeout(waitForMsg, 1000);
}

function setLongTimeout() {
    setTimeout(waitForMsg, 15000);
}

$(document).ready(function() {
                $.ajaxSetup({
                    async:true//set a global ajax requests as asynchronus
                });
                alert('Handler for .onload() called.');
                $.when(waitForMsg())
                    .done(successHandler, setShortTimeout)
                    .fail(errorHandler, setLongTimeout);

            });

            function waitForMsg(){
                return $.ajax({
                    type: "POST",
                    url: '<%=request.getContextPath()%>/notification/notify',
                    async: true, /* If set to non-async, browser shows page as "Loading.."*/
                    cache: false,
                    timeout:50000, /* Timeout in ms */
                    global:false
                });
            };

errorHandlerそして、successHandlerあなたの success: と error: コールバックになります。明確にするために省略しましたが、 setTimeout 部分は削除されています (これは deferred.done() および .fail() コールバックの一部になったため)。

それが機能するかどうか教えてください。

于 2012-10-18T11:02:46.013 に答える
2

私は PHP 開発者ですが、あなたの問題に遭遇しました。同じ動作である可能性があります。だから私はあなたに私の2セントを差し上げます。

問題を疑う行は次のとおりです。

events = (Events) request.getSession(false).getServletContext().getAttribute("events");

PHP では、セッションはファイルに保存されます。セッションが開いている間に php スクリプトでロング ポーリングを行うと、競合状態の問題が発生します。

原理は非常に単純です:

  1. リクエストによってセッションが開かれると、セッションが閉じられるまでファイルがロックされます。
  2. 他のリクエストがサーバーに来ると、セッションが前のリクエストから解放されるまでロックされます。

長いポーリングの場合、セッションが開かれ、情報を取得した直後 (少なくともイベントを待つ直前) に閉じられない場合、すべての要求がロックされるだけです。他のページでのセッションの使用。新しいタブを開いたとしても、1 つのブラウザーには 1 つのセッションしかないため、ロックされます。

于 2012-10-18T22:04:02.883 に答える
1

それはこれかもしれません:

        xhr=  $.ajax({ (...)

あなたのwaitForMsg関数で。

試す

    var xhr = (...)

グローバル オブジェクトで xhr を宣言しているため、2 つの異なる要求に応答できなくなっている可能性があります。

于 2012-10-18T09:10:36.150 に答える