Запросы MeteorJS очень медленные, если у пользователей есть активные сеансы - PullRequest
0 голосов
/ 30 апреля 2018

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

Нормальная скорость составляет менее 2 с для 1000 документов (извлекайте документы один за другим, и после некоторой локальной обработки данных обновление выполняется по одному; пакетных обновлений нет, поэтому оно выполняется довольно быстро). Но если веб-сервер некоторое время работал, а пользователи вошли в систему, эта функция может длиться вечно (например, 160 с для 1000 документов).

Я должен выйти из системы всех пользователей (db.users.update ({}, {$ set: {"services.resume.loginTokens": []}}, {multi: true})), чтобы вернуть скорость , После запуска запроса к БД скорость выполнения возвращается к ~ 2 с / 1000.

В чем проблема? Это не должно быть связано с индексом, так как это будет намного медленнее. Кроме того, на стороне БД нет журналов, указывающих на то, что БД является проблемой, и БД не имеет высокой загрузки ЦП. Хотя веб-сервер работает на 100% (за исключением этого, веб-сервер никогда не достигает даже 15%).

Веб-сервер AWS T2.small, и количество зарегистрированных пользователей (они все равно бездействуют, как я это делаю ночью) составляет около 10. У них есть несколько открытых подписок, я полагаю.

1 Ответ

0 голосов
/ 30 апреля 2018

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

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

Пример , приведенный в Руководстве по метеору , относится к примеру приложения Todos, но дает представление о том, как настроить и запустить массовую операцию в Meteor:

// This is how to get access to the raw MongoDB node collection that the Meteor server collection wraps
const batch = Lists.rawCollection().initializeUnorderedBulkOp();

//Mongo throws an error if we execute a batch operation without actual operations, e.g. when Lists was empty.
let hasUpdates = false;
Lists.find({todoCount: {$exists: false}}).forEach(list => {
  const todoCount = Todos.find({listId: list._id}).count();
  // We have to use pure MongoDB syntax here, thus the `{_id: X}`
  batch.find({_id: list._id}).updateOne({$set: {todoCount}});
  hasUpdates = true;
});

if(hasUpdates){
  // We need to wrap the async function to get a synchronous API that migrations expects
  const execute = Meteor.wrapAsync(batch.execute, batch);
  return execute();
}

Другие опции включают удаление реактивности из вашей обработки данных, поэтому обновления не все автоматически отправляются клиенту. Который немного более вовлечен

...