Логика работы с MongoDB в сервере на Node.JS?

Вопрос довольно банальный, но, кажется, нигде детально не рассматривается: как правильно организовать работу с БД, учитывая асинхронную природу node.js?

То есть когда коннектиться и закрывать соединение с БД — при каждом реквесте или один раз при запуске/остановке приложения?

Стоит ли кэшировать интерфейсные объекты коллекций и курсоры, которые можно переиспользовать?

И если держать соединение открытым, то как обрабатывать возможные разрывы?


Если вам известен хороший пример приложения, в котором всё это грамотно реализовано — поделитесь ссылкой на исходники. А то все примеры в документации сводятся к примитивной цепочке db.open() -> db.collection() -> collection.crud() -> db.close()
  • Вопрос задан
  • 15861 просмотр
Решения вопроса 1
dizballanze
@dizballanze
Software developer at Yandex
Насколько я понимаю, адаптер берет эту работу на себя. Т.е. в приложении об этом не нужно беспокоится, создал соединение один раз и пользуешься. А все остальное происходит за кулисами. Думаю об этом подробнее можно почитать в документации к адаптеру mongodb.
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
Я использую mongoosejs, пример хорошей архитектуры для него — github.com/madhums/node-express-mongoose-demo
В монгусе автоматом создается пул соединений (по умолчанию из 5 штук), есть опция — автореконнект.

Схматично работает так: при запуске приложения делаешь коннект с нужными тебе опциями — и все, во всех остальных модулях, просто require('mongoose') и делаешь с базой все, что угодно (так как модуль подтягивается закешированный с установленным соединением)
Ответ написан
Комментировать
@napa3um
При инициализации приложения однократно подключайся к базе данных с помощью MongoClient. Объект MongoClient создаёт пул соединений к БД, и сам восстановит соединение в случае разрыва. Также при инициализации рекомендую получить все необходимые коллекции для дальнейшей работы с ними, т.к. помимо оверхеда на создание JS-объектов в режиме strict получение коллекции вызывает проверку существования коллекции в базе данных. При этом закэшированные объекты коллекций будут использовать вышеописанные преимущества объекта MongoClient - пул соединений и переподключение в случае разрыва. Самостоятельно закрывать соединения не нужно, контекста и блокировок у соединения нет. Т.е., логика примерно такая (очень условно, без учёта архитектуры приложения):
// init db:
MongoClient.connect('mongodb://localhost:27017/dbName', function(err, db){
    cached.db = db;
    // init collection:
    db.collection('collName', { strict: true }, function(err, coll){
        cached.coll = coll;
    });
});
// usage in request:
cached.coll.insert(...);
Ответ написан
Комментировать
Stdit
@Stdit
При использовании одного соединения с БД есть серьёзный риск перегрузить сокет базы настолько, что именно он станет узким тормозящим местом всего проекта. Это довольно подлый нюанс, который не заметен на этапе тестирования и ввода в эксплуатацию (как и проблема гонок в mongo, но это отдельный разговор). У меня такое было, правда не на mongo, а на pg, но суть от этого не меняется: пока сокет базы занят перекачиванием больших объемов данных на специфических страницах, сайт будет заблокирован. Но и открывать соединение с базой на каждый запрос тоже не самая лучшая идея, так как на открытие, настройку и содержание соединения нужно несоразмерно много ресурсов (в том числе и на сервере БД). Поэтому должен быть пул соединений с БД. Драйверы mysql и pg такой пул имеют, насчет mongodb не уверен, так как не копал устройство драйверов mongo для nodejs.
Ответ написан
Комментировать
RUVATA
@RUVATA
Разработчик, гик, меломан, разгильдяй
Разные драйверы по разному решают эту задачу, нативный например вот так
github.com/mongodb/node-mongodb-native/blob/master/docs/articles/MongoClient.md
В исходниках можно посмотреть что-же на самом деле происходит.

Но в общем случае — правильным будет: открыть коннект -> записать/прочитать -> закрыть коннект

Есть исключительные случаи, когда такое поведение накладно, например у меня была задача, еогда очень маленькие порции данных приходили очень часто, настолько, что открытие/закрытие коннекта на фоне общего цикла «получили-записали» было просто неприлично большим.
Но в таком случае необходимо обязательно предусматривать сброс при первом существенном простое.
У монги как-то плоховато с длинными коннектами, ну по крайней мере так было раньше…
Ответ написан
Комментировать
Ноду не использовал, но в том-же твистед писал пулл соединений, который сам заботится обо всем.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы