wake-up-neo.com

Wie verwalte ich MongoDB-Verbindungen in einer Node.js-Webanwendung?

Ich benutze den node-mongodb-native Treiber mit MongoDB, um eine Website zu schreiben.

Ich habe einige Fragen zum Verwalten von Verbindungen:

  1. Reicht es aus, nur eine MongoDB-Verbindung für alle Anfragen zu verwenden? Gibt es Leistungsprobleme? Wenn nicht, kann ich eine globale Verbindung für die gesamte Anwendung einrichten?

  2. Wenn nicht, ist es gut, wenn ich eine neue Verbindung öffne, wenn eine Anfrage eingeht, und sie schließe, wenn die Anfrage bearbeitet wird? Ist es teuer, eine Verbindung zu öffnen und zu schließen?

  3. Sollte ich einen globalen Verbindungspool verwenden? Ich habe gehört, der Treiber hat einen nativen Verbindungspool. Ist es eine gute Wahl?

  4. Wie viele Verbindungen sollten verwendet werden, wenn ich einen Verbindungspool verwende?

  5. Gibt es andere Dinge, die ich beachten sollte?

247
Freewind

Der primäre Committer für node-mongodb-native sagt :

Sie öffnen do MongoClient.connect einmal, wenn Ihre App startet, und verwenden das DB-Objekt erneut. Es ist kein einzelner Verbindungspool .connect erstellt einen neuen Verbindungspool.

Um Ihre Frage direkt zu beantworten, verwenden Sie das aus MongoClient.connect () resultierende DB-Objekt erneut. Dies führt zu einem Pooling und zu einer spürbaren Geschwindigkeitssteigerung im Vergleich zum Öffnen/Schließen von Verbindungen bei jeder DB-Aktion.

424
Max

Öffnen Sie eine neue Verbindung, wenn die Anwendung Node.js gestartet wird, und verwenden Sie das vorhandene Verbindungsobjekt db erneut:

/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;

Quelle: So öffnen Sie Datenbankverbindungen in einer Node.js/Express-App

39

Hier ist ein Code, der Ihre MongoDB-Verbindungen verwaltet.

var MongoClient = require('mongodb').MongoClient;
var url = require("../config.json")["MongoDBURL"]

var option = {
  db:{
    numberOfRetries : 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;

Wenn Sie den Server starten, rufen Sie initPool auf

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

In jedem anderen Modul können Sie dann Folgendes tun:

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

Dies basiert auf MongoDB-Dokumentation . Schau es dir an.

16
Yaki Klein

Verwalten Sie Mongo-Verbindungspools in einem einzelnen eigenständigen Modul. Dieser Ansatz bietet zwei Vorteile. Erstens bleibt Ihr Code modular und lässt sich leichter testen. Zweitens müssen Sie Ihre Datenbankverbindung nicht in Ihrem Anforderungsobjekt verwechseln, das NICHT der Ort für ein Datenbankverbindungsobjekt ist. (In Anbetracht der Natur von JavaScript würde ich es als sehr gefährlich betrachten, irgendetwas in ein Objekt zu mischen, das durch Bibliothekscode erstellt wurde). Daher müssen Sie nur ein Modul in Betracht ziehen, das zwei Methoden exportiert. connect = () => Promise und get = () => dbConnectionObject.

Mit einem solchen Modul können Sie sich zunächst mit der Datenbank verbinden

// 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);
    });

Während des Flugs kann Ihre App einfach get() aufrufen, wenn sie eine DB-Verbindung benötigt.

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

Wenn Sie Ihr DB-Modul wie folgt einrichten, können Sie nicht nur sicherstellen, dass Ihre Anwendung nur dann startet, wenn Sie über eine Datenbankverbindung verfügen, sondern auch global auf Ihren fehlerhaften Datenbankverbindungspool zugreifen wenn Sie keine Verbindung haben.

// 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;
}
11
Stewart

Wenn Sie Express.js haben, können Sie express-mongo-db verwenden, um die MongoDB-Verbindung zwischen Anforderungen ohne Pool zwischenzuspeichern und gemeinsam zu nutzen (da die akzeptierte Antwort besagt, dass dies der richtige Weg ist, die Verbindung gemeinsam zu nutzen). .

Wenn nicht, können Sie den Quellcode anzeigen und in einem anderen Framework verwenden.

11
floatdrop

Ich habe einen generischen Pool mit Redis-Verbindungen in meiner App verwendet - ich kann es nur empfehlen. Es ist generisch und ich weiß definitiv, dass es mit MySQL funktioniert, so dass ich nicht glaube, dass Sie Probleme damit und mit Mongo haben werden

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

6
ControlAltDel

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

Überprüfen Sie die Quelle des Mungos. Sie öffnen eine Verbindung und binden sie an ein Modellobjekt. Wenn das Modellobjekt erforderlich ist, wird eine Verbindung zur Datenbank hergestellt. Der Treiber kümmert sich um das Verbindungs-Pooling.

4
srquinn

Sie sollten eine Verbindung als Dienst erstellen und bei Bedarf wiederverwenden.

// 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;

meine App.js Probe

// 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}`);
  });
});

und verwenden Sie es, wo immer Sie wollen

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

Ich habe den folgenden Code in meinem Projekt implementiert, um das Verbindungs-Pooling in meinem Code zu implementieren, sodass eine minimale Verbindung in meinem Projekt erstellt und die verfügbare Verbindung wiederverwendet wird

/* 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");

});
2
Aditya Parmar

Die beste Methode zum Implementieren von Verbindungspooling ist, eine globale Arrayvariable zu erstellen, die den Datenbanknamen mit dem von MongoClient zurückgegebenen Verbindungsobjekt enthält, und diese Verbindung dann wieder zu verwenden, wenn Sie eine Verbindung mit Database herstellen müssen.

  1. Definieren Sie in Ihrer Server.js var global.dbconnections = [];

  2. Erstellen Sie einen Dienst mit dem Namen connectionService.js. Es werden 2 Methoden getConnection und createConnection zur Verfügung stehen. Wenn der Benutzer getConnection () aufruft, findet er Details in der globalen Verbindungsvariablen und gibt Verbindungsdetails zurück, falls bereits vorhanden. Andernfalls ruft er createConnection () auf und gibt Verbindungsdetails zurück.

  3. Rufen Sie diesen Service mit db_name auf und es wird ein Verbindungsobjekt zurückgegeben, falls es bereits ein anderes hat. Es wird eine neue Verbindung erstellt und an Sie zurückgegeben.

Ich hoffe es hilft :)

Hier ist der connectionService.js Code:

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;
} 
1
RRPatel