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

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

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

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

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

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

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

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



답변

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

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

따라서 질문에 직접 대답 하려면의 결과 인 db 객체를 재사용하십시오MongoClient.connect() . 이것은 풀링을 제공하며 각 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


답변

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

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