Comment gérer les connexions MongoDB dans une application Web Node.js?

J’utilise le pilote node-mongodb-native avec MongoDB pour écrire un site Web.

J’ai des questions sur la gestion des connexions:

  1. Est-ce suffisant d’utiliser une seule connexion MongoDB pour toutes les demandes? Y a-t-il des problèmes de performance? Si non, puis-je configurer une connexion globale à utiliser dans toute l’application?

  2. Si ce n’est pas le cas, est-ce que je peux ouvrir une nouvelle connexion lorsque la demande arrive et la fermer lorsque la demande est traitée? Est-ce cher d’ouvrir et de fermer une connexion?

  3. Dois-je utiliser un pool de connexions global? J’ai entendu le pilote avoir un pool de connexions natif. est-ce un bon choix?

  4. Si j’utilise un pool de connexions, combien de connexions faut-il utiliser?

  5. Y a-t-il d’autres choses que je devrais remarquer?

Le committer principal de node-mongodb-native dit :

Vous ouvrez une fois MongoClient.connect lorsque votre application démarre et réutilise l’object db. Ce n’est pas un pool de connexions singleton, chaque .connect crée un nouveau pool de connexions.

Donc, pour répondre directement à votre question, réutilisez l’object db résultant de MongoClient.connect (). Cela vous permet de vous regrouper et vous permettra d’augmenter considérablement la vitesse par rapport aux connexions d’ouverture / fermeture sur chaque action de la firebase database.

Ouvrez une nouvelle connexion au démarrage de l’application Node.js et réutilisez l’object de connexion db existant:

/server.js

 import express from 'express'; import Promise from 'bluebird'; import logger from 'winston'; import { MongoClient } from 'mongodb'; import config from './config'; import usersRestApi from './api/users'; const app = express(); app.use('/api/users', usersRestApi); app.get('/', (req, res) => { res.send('Hello World'); }); // Create a MongoDB connection pool and start the application // after the database connection is ready MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => { if (err) { logger.warn(`Failed to connect to the database. ${err.stack}`); } app.locals.db = db; app.listen(config.port, () => { logger.info(`Node.js app is listening at http://localhost:${config.port}`); }); }); 

/api/users.js

 import { Router } from 'express'; import { ObjectID } from 'mongodb'; const router = new Router(); router.get('/:id', async (req, res, next) => { try { const db = req.app.locals.db; const id = new ObjectID(req.params.id); const user = await db.collection('user').findOne({ _id: id }, { email: 1, firstName: 1, lastName: 1 }); if (user) { user.id = req.params.id; res.send(user); } else { res.sendStatus(404); } } catch (err) { next(err); } }); export default router; 

Source: Comment ouvrir les connexions de firebase database dans une application Node.js / Express

Voici un code pour gérer vos connexions MongoDB.

 var MongoClient = require('mongodb').MongoClient; var url = require("../config.json")["MongoDBURL"] var option = { db:{ numberOfResortinges : 5 }, server: { auto_reconnect: true, poolSize : 40, socketOptions: { connectTimeoutMS: 500 } }, replSet: {}, mongos: {} }; function MongoPool(){} var p_db; function initPool(cb){ MongoClient.connect(url, option, function(err, db) { if (err) throw err; p_db = db; if(cb && typeof(cb) == 'function') cb(p_db); }); return MongoPool; } MongoPool.initPool = initPool; function getInstance(cb){ if(!p_db){ initPool(cb) } else{ if(cb && typeof(cb) == 'function') cb(p_db); } } MongoPool.getInstance = getInstance; module.exports = MongoPool; 

Lorsque vous démarrez le serveur, appelez initPool

 require("mongo-pool").initPool(); 

Ensuite, dans tout autre module, vous pouvez effectuer les opérations suivantes:

 var MongoPool = require("mongo-pool"); MongoPool.getInstance(function (db){ // Query your MongoDB database. }); 

Ceci est basé sur la documentation de MongoDB . Jetez un coup d’oeil.

Si vous avez Express.js, vous pouvez utiliser express-mongo-db pour mettre en cache et partager la connexion MongoDB entre les requêtes sans pool (puisque la réponse acceptée indique que c’est le bon moyen de partager la connexion).

Sinon – vous pouvez consulter son code source et l’utiliser dans un autre cadre.

Gérer les pools de connexions mongo dans un seul module autonome. Cette approche offre deux avantages. Tout d’abord, votre code rest modulaire et plus facile à tester. Deuxièmement, vous n’êtes pas obligé de mélanger votre connexion de firebase database dans votre object de requête, ce qui n’est PAS l’endroit pour un object de connexion à une firebase database. (Compte tenu de la nature de JavaScript, je considère très dangereux de mélanger quoi que ce soit à un object construit par code de bibliothèque). Donc, avec cela, il suffit de considérer un module qui exporte deux méthodes. connect = () => Promise et get = () => dbConnectionObject .

Avec un tel module, vous pouvez d’abord vous connecter à la firebase database

 // runs in boot.js or what ever file your application starts with const db = require('./myAwesomeDbModule'); db.connect() .then(() => console.log('database connected')) .then(() => bootMyApplication()) .catch((e) => { console.error(e); // Always hard exit on a database connection error process.exit(1); }); 

En vol, votre application peut simplement appeler get() quand elle a besoin d’une connexion à la firebase database.

 const db = require('./myAwesomeDbModule'); db.get().find(...)... // I have excluded code here to keep the example simple 

Si vous configurez votre module de firebase database de la même manière que ci-dessous, vous aurez non seulement un moyen de vous assurer que votre application ne démarrera que si vous avez une connexion de firebase database. si vous n’avez pas de connexion

 // myAwesomeDbModule.js let connection = null; module.exports.connect = () => new Promise((resolve, reject) => { MongoClient.connect(url, option, function(err, db) { if (err) { reject(err); return; }; resolve(db); connection = db; }); }); module.exports.get = () => { if(!connection) { throw new Error('Call connect first!'); } return connection; } 

J’ai utilisé le pool générique avec des connexions redis dans mon application – je le recommande vivement. Son générique et je sais vraiment que cela fonctionne avec mysql donc je ne pense pas que vous aurez des problèmes avec elle et mongo

https://github.com/coopernurse/node-pool

http://mongoosejs.com/docs/api.html

Découvrez la source de Mongoose. Ils ouvrent une connexion et la lient à un object Model. Ainsi, lorsque l’object Model est requirejs, une connexion est établie avec la DB. Le pilote prend en charge le regroupement des connexions.

Vous devez créer une connexion en tant que service, puis la réutiliser en cas de besoin.

 // db.service.js import { MongoClient } from "mongodb"; import database from "../config/database"; const dbService = { db: undefined, connect: callback => { MongoClient.connect(database.uri, function(err, data) { if (err) { MongoClient.close(); callback(err); } dbService.db = data; console.log("Connected to database"); callback(null); }); } }; export default dbService; 

mon exemple App.js

 // App Start dbService.connect(err => { if (err) { console.log("Error: ", err); process.exit(1); } server.listen(config.port, () => { console.log(`Api runnning at ${config.port}`); }); }); 

et l’utiliser où vous voulez avec

 import dbService from "db.service.js" const db = dbService.db 

J’ai implémenté le code ci-dessous dans mon projet pour implémenter le regroupement de connexions dans mon code afin de créer une connexion minimale dans mon projet et de réutiliser la connexion disponible

 /* Mongo.js*/ var MongoClient = require('mongodb').MongoClient; var url = "mongodb://localhost:27017/yourdatabasename"; var assert = require('assert'); var connection=[]; // Create the database connection establishConnection = function(callback){ MongoClient.connect(url, { poolSize: 10 },function(err, db) { assert.equal(null, err); connection = db if(typeof callback === 'function' && callback()) callback(connection) } ) } function getconnection(){ return connection } module.exports = { establishConnection:establishConnection, getconnection:getconnection } /*app.js*/ // establish one connection with all other routes will use. var db = require('./routes/mongo') db.establishConnection(); //you can also call with callback if you wanna create any collection at starting /* db.establishConnection(function(conn){ conn.createCollection("collectionName", function(err, res) { if (err) throw err; console.log("Collection created!"); }); }; */ // anyother route.js var db = require('./mongo') router.get('/', function(req, res, next) { var connection = db.getconnection() res.send("Hello"); }); 

La meilleure approche pour implémenter le regroupement de connexions est de créer une variable de tableau global contenant le nom de firebase database avec l’object de connexion renvoyé par MongoClient, puis de réutiliser cette connexion chaque fois que vous devez contacter Database.

  1. Dans votre Server.js, définissez var global.dbconnections = [];

  2. Créez un service nommant connectionService.js. Il aura 2 méthodes getConnection et createConnection. Ainsi, lorsque l’utilisateur appelle getConnection (), il trouvera des détails dans la variable de connexion globale et retournera les détails de la connexion s’il existe déjà, il appellera createConnection () et retournera les détails de la connexion.

  3. Appelez ce service en utilisant nom_bd et il retournera un object de connexion s’il existe déjà, il créera une nouvelle connexion et vous le renverra.

J’espère que cela aide 🙂

Voici le code connectionService.js:

 var mongo = require('mongoskin'); var mongodb = require('mongodb'); var Q = require('q'); var service = {}; service.getConnection = getConnection ; module.exports = service; function getConnection(appDB){ var deferred = Q.defer(); var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB) if(connectionDetails){deferred.resolve(connectionDetails.connection); }else{createConnection(appDB).then(function(connectionDetails){ deferred.resolve(connectionDetails);}) } return deferred.promise; } function createConnection(appDB){ var deferred = Q.defer(); mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=> { if(err) deferred.reject(err.name + ': ' + err.message); global.dbconnections.push({appDB: appDB, connection: database}); deferred.resolve(database); }) return deferred.promise; }