Бэкэнд ExpressJS зависает со слишком большим количеством запросов - PullRequest
0 голосов
/ 14 марта 2012

У меня есть экспресс-приложение, работающее с Sequelize.js в качестве ORM. Мое экспресс-приложение получает запросы от моего основного приложения на Rails, и из-за междоменной политики эти запросы выполняются с помощью getJSON.

На клиенте запрос запускается, когда пользователь нажимает клавишу. Все идет хорошо, и экспресс регистрирует запросы, выполняемые (и выполняемые json) каждый раз, когда пользователь нажимает клавишу. Даже пытаясь ударить быстро, все работает хорошо. Но всякий раз, когда я оставляю нажатой клавишу (или, может быть, несколько клиентов нажимают клавишу очень быстро), поскольку он начинает запускать множество запросов, в какой-то момент сервер просто зависает, все запросы с этого момента остаются отложенными (я вижу, что на вкладке Сеть Chrome Dev Tools), и они медленно начинают время ожидания. Я должен перезагрузить сервер, чтобы он снова ответил.

Код сервера для моего запроса:

models.Comment.findAllPublic(req.params.pId, req.params.sId, function(comments){
                var json = comments.map(function(comment){
                    var com = {};
                    ['user_id','user_avatar', 'user_slug', 'user_name', 'created_at', 'text', 'private', 'is_speaker_note'].forEach(function(key){
                        com[key]=comment[key];
                    });
                    return com;
                });

                res.json({comments: json});
        }); 

И метод findAllPublic из модели Comment (это модель Sequelize):

findAllPublicAndMyNotes: function(current_user, presentationId, slideId, cb){
                db.query("SELECT * FROM `comments` WHERE  commentable_type='Slide' AND commentable_id=(SELECT id from `slides` where `order_in_presentation`="+slideId+" AND `presentation_id`="+presentationId+") AND (`private` IS FALSE OR (`private` IS TRUE AND `user_id`="+current_user+" AND `is_speaker_note` IS FALSE))",self.Comment).on('success', cb).on('failure',function(err){console.log(err);});
            }

Как избежать зависания сервера? Я оставляю в запросе какой-то блокирующий код, который может медленно зависать на сервере по мере поступления новых запросов?

Сначала я подумал, что это может быть проблемой из-за «forEach» при составлении объекта json из модели Sequelize, но я также попытался оставить обратный вызов для запроса mysql пустым, просто отвечая пустым json, и он также завис .

Может быть, это проблема коннектора mysql? Когда сервер зависает, я обычно могу запустить консоль mysql и выполнить запросы к моей базе данных, и он также отвечает, поэтому я не знаю, в этом ли проблема.

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

Есть мысли? Заранее спасибо за помощь: D

1 Ответ

2 голосов
/ 14 марта 2012

Две вещи:

  1. Кажется, у вас есть какой-то путь, по которому res.render не вызывается. Возможно, база данных, к которой вы подключаетесь, сбрасывает соединение с вашим сервером Express после абсурдного числа запросов, и обратный вызов никогда не срабатывает (и нет database.on('close', function() { // Handle disconnect from DB, perhaps auto-restarting }) кода для его перехвата.
  2. Ваш код на стороне клиента должен определить, когда AJAX-запрос на нажатие клавиши все еще ожидает выполнения, пока запускается новый, и отменять старый. Я предполагаю, getJSON это метод jQuery? Предполагая, что это JQuery, то вам нужно что-то вроде следующего

.

var currKeyRequest = null;
function callOnKeyUp() {
    var searchText = $('#myInputBox').value;
    if(currKeyRequest) {
        currKeyRequest.reject();
        currKeyRequest = null;
    }
    currKeyRequest = $.getJSON('path/to/server', function(json) {
        currKeyRequest = null;
        // Use JSON code
    });
}

Таким образом, вы уменьшаете нагрузку на клиента, задержку функции автозаполнения (но почему бы не использовать автозаполнение пользовательского интерфейса jQuery, если это то, что вам нужно?), И вы можете сохранить сервер от некоторой нагрузки а также, если нажатия клавиш выполняются быстрее, чем рукопожатие с сервером (возможно, при наличии хорошего набора текста в нескольких часах полета).

...