IT story

Node.js 웹 애플리케이션에서 MongoDB 연결을 어떻게 관리합니까?

hot-time 2020. 4. 4. 10:59
반응형

Node.js 웹 애플리케이션에서 MongoDB 연결을 어떻게 관리합니까?


내가 사용하고 노드 MongoDB를 네이티브 웹 사이트를 작성하여 MongoDB와 드라이버를.

연결 관리 방법에 대한 몇 가지 질문이 있습니다.

  1. 모든 요청에 ​​대해 하나의 MongoDB 연결 만 사용하면 충분합니까? 성능 문제가 있습니까? 그렇지 않은 경우 전체 응용 프로그램에서 사용할 전역 연결을 설정할 수 있습니까?

  2. 그렇지 않은 경우 요청이 도착할 때 새 연결을 열고 요청을 처리 할 때 닫는 것이 좋습니까? 연결을 열고 닫는 데 비용이 많이 듭니까?

  3. 글로벌 연결 풀을 사용해야합니까? 드라이버에 기본 연결 풀이 있다고 들었습니다. 좋은 선택입니까?

  4. 연결 풀을 사용하는 경우 몇 개의 연결을 사용해야합니까?

  5. 주목해야 할 다른 것들이 있습니까?


node-mongodb-native의 주요 커미터는 다음과 같이 말합니다 .

앱이 부팅되고 db 객체를 재사용 할 때 do MongoClient.connect를 한 번 엽니 다. 각 .connect는 단일 연결 풀이 아니므로 새 연결 풀을 만듭니다.

따라서 질문에 직접 대답하려면 MongoClient.connect ()에서 생성 된 db 객체를 재사용하십시오. 이것은 풀링을 제공하고 각 db 조치에서 연결을 열고 닫는 것과 비교하여 눈에 띄는 속도 증가를 제공합니다.


Node.js 애플리케이션이 시작될 때 새 연결을 열고 기존 db연결 오브젝트를 재사용하십시오 .

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

출처 : Node.js / Express 앱에서 데이터베이스 연결을 여는 방법


다음은 MongoDB 연결을 관리하는 코드입니다.

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;

서버를 시작할 때 전화 initPool

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

그런 다음 다른 모듈에서 다음을 수행 할 수 있습니다.

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

이것은 MongoDB 문서를 기반으로 합니다 . 한번보세요


단일 자체 포함 모듈에서 mongo 연결 풀을 관리하십시오. 이 접근법은 두 가지 이점을 제공합니다. 먼저 코드를 모듈화하고 테스트하기 쉽게 유지합니다. 둘째, 데이터베이스 연결 개체의 위치가 아닌 요청 개체에서 데이터베이스 연결을 강제로 혼합하지 마십시오. (JavaScript의 특성을 감안할 때 라이브러리 코드로 구성된 객체에 무엇이든 혼합하는 것이 매우 위험하다고 생각합니다). 따라서 두 가지 방법을 내보내는 모듈 만 고려하면됩니다. connect = () => Promise그리고 get = () => dbConnectionObject.

이러한 모듈을 사용하면 먼저 데이터베이스에 연결할 수 있습니다

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

비행 중 앱은 get()DB 연결이 필요할 때 간단히 호출 수 있습니다 .

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

다음과 같은 방법으로 db 모듈을 설정하면 데이터베이스 연결이없는 한 응용 프로그램이 부팅되지 않도록하는 방법이있을뿐 아니라 데이터베이스 연결 풀에 액세스하는 전역 방법도 있습니다. 연결되지 않은 경우

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

Express.js가 있으면 풀없이 요청간에 MongoDB 연결을 캐싱하고 공유하기 위해 express-mongo-db사용할 수 있습니다 (허용 된 답변이 연결을 공유하는 올바른 방법이라고 말했기 때문에).

그렇지 않은 경우-소스 코드를보고 다른 프레임 워크에서 사용할 수 있습니다.


내 앱에서 redis 연결과 함께 일반 풀을 사용하고 있습니다. 적극 권장합니다. 그것의 제네릭과 나는 그것이 mysql과 함께 작동한다는 것을 확실히 알고 있으므로 당신은 그것과 몽고에 아무런 문제가 없을 것이라고 생각하지 않는다.

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


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

몽구스의 출처를 확인하십시오. 연결을 열고 모델 객체에 바인딩하므로 모델 객체가 필요할 때 DB에 연결됩니다. 드라이버는 연결 풀링을 처리합니다.


서비스로 연결을 만든 다음 필요할 때 다시 사용해야합니다.

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

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

원하는 곳 어디에서나 사용하십시오

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

내 코드에서 연결 풀링을 구현하기 위해 프로젝트에서 아래 코드를 구현 했으므로 프로젝트에서 최소 연결을 만들고 사용 가능한 연결을 재사용합니다.

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

});

연결 풀링을 구현하는 가장 좋은 방법은 MongoClient가 리턴 한 연결 오브젝트로 db 이름을 보유한 전역 배열 변수를 작성하고 데이터베이스에 접속해야 할 때마다 해당 연결을 재사용하는 것입니다.

  1. Server.js에서 var global.dbconnections = [];

  2. 서비스 이름 지정 connectionService.js를 작성하십시오. getConnection 및 createConnection의 두 가지 메소드가 있습니다. 따라서 사용자가 getConnection ()을 호출하면 전역 연결 변수에서 세부 정보를 찾고 이미 존재하는 경우 연결 세부 정보를 반환합니다. 그렇지 않으면 createConnection ()을 호출하고 연결 세부 정보를 반환합니다.

  3. db_name을 사용하여이 서비스를 호출하면 연결 오브젝트가 이미 있으면 연결 오브젝트를 리턴하고 새 연결을 작성하여 리턴합니다.

그것이 도움이되기를 바랍니다 :)

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

참고 URL : https://stackoverflow.com/questions/10656574/how-do-i-manage-mongodb-connections-in-a-node-js-web-application

반응형