Долгие опросы замораживают браузер и блокируют другие запросы ajax

Я пытаюсь реализовать длинный опрос в моемSpring-MVC Web App но он замораживает мой браузер и другие запросы после того, как 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: '/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('/notification/notify');
            $(document).bind('feed.comet', updateFeed);
            $(document).bind('.comet', catchAll);

Не появляется ни одно окно с предупреждением .. :(

 ern012 окт. 2012 г., 11:21
Сколько существует одновременных соединений? Некоторые браузеры ограничивают 2 / веб-страницу.
 bhb08 окт. 2012 г., 08:55
Видите ли вы какие-либо проблемы / ошибки в вашем firebug. Если данные, поступающие с сервера, огромны, это может привести к зависанию браузера.
 Dangling Piyush08 окт. 2012 г., 09:01
Нет ошибки в firebug. И данные также только содержимое строки.
 bhb08 окт. 2012 г., 08:49
я думаю, что вы используете setTimeout вместо setInterval. Проверьтеэтот
 Dangling Piyush08 окт. 2012 г., 08:53
я думаю, что это не проблема для замораживания, это идеально, потому что я хочу вызывать метод только один раз, а не снова и снова (в случае успеха или ошибки).

Ответы на вопрос(7)

Когда я столкнулся с подобной проблемой, мой браузер завис как-то с AJAX-запросами. Подсказка: вместо этогоwaitForMsg () прямо, попробуйSetTimeout (»waitForMsg ()», 10).

 Dangling Piyush12 окт. 2012 г., 12:06
Попробовал не работающий браузер, покажет символ загрузки и зависает.

Это может быть так:

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

в вашей функции waitForMsg.

Пытаться

    var xhr = (...)

Возможно, вы объявляете xhr в глобальном объекте, что делает невозможным отвечать на два разных запроса.

Вы можете попробовать переписать поведение, используя 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: '/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 будет ваш успех: и error: обратные вызовы, которые я пропустил для ясности, с удаленной частью setTimeout (так как теперь она является частью обратных вызовов deferred.done () и .fail ()).

Дайте мне знать, если это работает.

Решение Вопроса

Кажется, у вас есть пустой цикл while в коде вашего браузера ... это очень интенсивный способ ожидания события.

Если никаких событий не произойдет, клиент завершит запрос по истечении заданного вами времени ожидания в 50 секунд. Но я'я не уверен, что серверный поток тоже убит или "в то время как» навсегда (если нет события). Следующий запрос запустит второй поток сервера, который тоже зависает в цикле while. Может быть, количество пустых циклов while является излишним для сервера, так что он перестает принимать больше запросов. Таким образом, после некоторых запросов (каждый из которых запускает бесконечный серверный поток) клиент всегда ожидает новый запрос ... потому что он может 'быть обработано сервером.

ps: в случае успеха вы прокомментировали ожидание 1 секунду, но установили таймаут на 10000 (10 секунд)

 lrsjng17 окт. 2012 г., 15:52
@DanglingPiyush все еще зависает?
 Dangling Piyush14 окт. 2012 г., 19:25
Это победилоЧеловек не работает, потому что такое поведение не в нашей власти, поэтому мы будем отправлять разные ответы каждому клиенту, и мы можемЯ даже уверен, что каждый клиент получит один и тот же ответ. Я пробовал его раньше.
 Dangling Piyush18 окт. 2012 г., 06:34
@Irsjng да .. :( .. Я думаю, мне нужен другой подход для достижения этой цели.
 lrsjng13 окт. 2012 г., 19:29
Просто чтобы проверить, является ли это причиной, добавьте следующую строку в цикл while:Thread.currentThread().sleep(1000);  Это отправит текущий поток в спящий режим, чтобы другие потоки могли его запустить. Отрегулируйте время ожидания на требуемое время реакции.
 lrsjng14 окт. 2012 г., 20:24
Ваш вопрос и проблема на данный момент в том, почему ваш браузер зависает ... и вопрос в том, является ли перегрузка сервера причиной этого. это изменение все еще вызывает зависание браузера?
 Dangling Piyush13 окт. 2012 г., 19:13
Получил вашу точку зрения, как я могу решить эту проблему, если вы предоставляете мне код, чтобы сделать длинный опрос эффективно. Спасибо

К вашему сведению, вот проект, который может вам помочь:https://github.com/SeanOC/jquery.comet

В общем, я бы искал API-интерфейсы комет JavaScript, которые могут поддерживать веб-сокеты, если они доступны на клиент-сервере, с постепенным переходом к долгому опросу. API должен обрабатывать все кровавые подробности, позволяя вам сосредоточиться на приложении.

Вот'Ссылка на старую статью о додзё на эту тему:http://dojotoolkit.org/features/1.6/dojo-websocket

Удачи.

 Dangling Piyush18 окт. 2012 г., 10:47
Пробовал решение по первой ссылке, но не работает ... Обновление добавлено в вопрос.

Я разработчик PHP, но я столкнулся с вашей проблемой, и это может быть то же самое поведение. Поэтому я даю вам свои 2 цента и надеюсь, что этоЯ помогу тебе.

Строка, которая заставляет меня подозревать проблему:

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

В PHP сессии хранятся в файлах, и если мы долго опрашиваем PHP-скрипт, когда сессия открыта, мы встречаемся ссостояние гонки проблема.

Принцип довольно прост:

Когда запрос открывает сеанс, файл блокируется, пока сеанс не будет закрыт.Если другие запросы поступят на сервер, они будут заблокированы до тех пор, пока сеанс не будет освобожден от предыдущего запроса.

В случае длительного опроса, если сеанс открывается и не закрывается сразу после получения информации (по крайней мере, непосредственно перед ожиданием событий), все запросы просто блокируются, вы можете 'нигде на сайте, если выВы используете сессии на других страницах. Даже если вы откроете новую вкладку, потому что для одного браузера есть только один сеанс, вы 'заблокирован

 Dangling Piyush19 окт. 2012 г., 07:18
Я делаю это потому, что хочу отразить одно и то же уведомление о событии для каждого пользовательского браузера, поэтому я считаю, что лучшим вариантом является контекст. Но я'Я попробую то, что вы предложили. Но у php есть session_write_close, я неЯ думаю, у Java есть такая вещь.

Похоже, вы испытали блокировку файла сеанса

Для PHP

использованиеsession_write_close() когда ты нене нужно значение сеанса

 emerino04 мар. 2015 г., 08:32
не совсем то, что опер спросил, но голосовал против, потому что это было именно то, что я искал

Ваш ответ на вопрос