2012-03-14 3 views
0

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

На клиенте запрос запускается, когда пользователь нажимает клавишу. Все идет хорошо и выражает журналы выполняемых запросов (и 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 от модели Комментарий (это модель 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

+0

Вы создаете что-то вроде autosuggest? –

ответ

2

Две вещи:

  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 UI, если это то, что вам нужно?), и вы также можете сохранить сервер от некоторой нагрузки, если клавиши быстрее чем квитирование с сервером (возможно, с хорошей машиной прикосновения несколько часов полета).

+0

Привет, спасибо за ваш ответ, он заставил меня найти некоторую информацию, которая, я думаю, может быть связана с этой проблемой. То, что я разрабатываю, представляет собой систему представления в реальном времени, и когда пользователь нажимает клавишу вперед/назад, слайды загружаются и комментарии пользователя на этих слайдах также загружаются. Так что это не автозаполнение :). Благодаря вашему комментарию я обнаружил, что sequelize.js на данный момент использует соединитель node-mysql, где мы можем найти эту [открытую проблему] (https://github.com/felixge/node-mysql/issues/ 113). Считаете ли вы, что это может быть связано? Автор продолжения также говорит, что он собирается изменить разъем. – scumah

+0

Кроме того, я пробовал решение для управления ожидающими запросами на клиенте и, к сожалению, кажется, что объект, возвращаемый методом getJSON jquery, не реализует отклонение, хотя он реализует некоторые другие методы элемента Deferred. Есть какие-нибудь подсказки по этому поводу? Спасибо за вашу помощь. – scumah

+2

@scumah: Не дискредитировать работу Феликса, но я думаю, что он слишком тонкий. Мне пришлось разбить библиотеку его раньше, потому что он просто не хотел даже просматривать патч, который я отправил в относительно простую библиотеку (node-dateformat). Эта проблема звучит так, что это очень хорошо может быть причиной проблемы - если она отключается, она не запускает никаких событий на этом сбое и не пытается повторно подключиться. Что касается getJSON, не предоставляющего «правильный» объект, какую версию jQuery вы используете? Старые версии просто предоставляют объекты '' XMLHttpRequest'', и вы можете просто '' .abort() '' –

Смежные вопросы