Fre*_*ind 260 database-connection connection-pooling mongodb node.js
我正在使用MongoDB 的node-mongodb-native驱动程序来编写一个网站.
我有一些关于如何管理连接的问题:
对所有请求只使用一个MongoDB连接是否足够?有任何性能问题吗?如果没有,我可以设置全局连接以在整个应用程序中使用吗?
如果没有,如果我在请求到达时打开一个新连接并在处理请求时关闭它是否合适?打开和关闭连接是否昂贵?
我应该使用全局连接池吗?我听说驱动程序有一个本机连接池.这是一个不错的选择吗?
如果我使用连接池,应该使用多少个连接?
还有其他我应该注意的事情吗?
Max*_*Max 436
当您的应用程序启动并重用db对象时,您可以打开一次MongoClient.connect.它不是单独的连接池,每个.connect都会创建一个新的连接池.
因此,要直接回答您的问题,请重用MongoClient.connect()生成的db对象.这为您提供了池化,与每个数据库操作上的打开/关闭连接相比,它将提供明显的速度提升.
Kon*_*kus 40
在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}`);
});
});
Run Code Online (Sandbox Code Playgroud)
/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;
Run Code Online (Sandbox Code Playgroud)
Yak*_*ein 16
以下是一些将管理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;
Run Code Online (Sandbox Code Playgroud)
启动服务器时,请致电 initPool
require("mongo-pool").initPool();
Run Code Online (Sandbox Code Playgroud)
然后在任何其他模块中,您可以执行以下操作:
var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
// Query your MongoDB database.
});
Run Code Online (Sandbox Code Playgroud)
这基于MongoDB文档.看看吧.
Ste*_*art 13
在单个自包含模块中管理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);
});
Run Code Online (Sandbox Code Playgroud)
在飞行中,您的应用程序可以get()
在需要数据库连接时调用.
const db = require('./myAwesomeDbModule');
db.get().find(...)... // I have excluded code here to keep the example simple
Run Code Online (Sandbox Code Playgroud)
如果以与以下相同的方式设置数据库模块,除了有数据库连接之外,您还有办法确保应用程序无法启动,您还可以使用全局方式访问数据库连接池,这将导致错误如果你没有连接.
// 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;
}
Run Code Online (Sandbox Code Playgroud)
flo*_*rop 11
如果您有Express.js,您可以使用express-mongo-db进行缓存并在没有池的请求之间共享MongoDB连接(因为接受的答案表明这是共享连接的正确方法).
如果没有 - 您可以查看其源代码并在另一个框架中使用它.
小智 8
您应该创建一个连接作为服务,然后在需要时重用它。
// 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;
Run Code Online (Sandbox Code Playgroud)
我的 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}`);
});
});
Run Code Online (Sandbox Code Playgroud)
并随心所欲地使用它
import dbService from "db.service.js"
const db = dbService.db
Run Code Online (Sandbox Code Playgroud)
我一直在我的应用程序中使用带有redis连接的通用池 - 我强烈推荐它.它的通用和我肯定知道它适用于mysql所以我认为你不会有任何问题和mongo
https://github.com/coopernurse/node-pool
归档时间: |
|
查看次数: |
97257 次 |
最近记录: |