Node.js 上 MongoDB 连接的最佳实践是啥?
Posted
技术标签:
【中文标题】Node.js 上 MongoDB 连接的最佳实践是啥?【英文标题】:What's the best practice for MongoDB connections on Node.js?Node.js 上 MongoDB 连接的最佳实践是什么? 【发布时间】:2012-08-01 18:02:48 【问题描述】:这对我来说有点不清楚(我刚刚开始使用 Node 和 Mongo),并且由于服务器性能和压力(我想这是另一个问题,但我会得到到文章末尾)。
所以,假设我正在使用 Node.js 和 Restify 编写 API,其中每个 API 端点对应一个函数,我应该:
a) 打开数据库连接并将其存储在全局变量中,然后在每个函数中使用它? 示例:
// requires and so on leave me with a db var, assume auto_reconnect: true
function openDB()
db.open(function(err, db)
// skip err handling and so on
return db;
var myOpenDB = openDB(); // use myOpenDB in every other function I have
b) 打开数据库连接,然后把所有东西都放在一个巨大的闭包中? 示例:
// same as above
db.open(function(err, db)
// do everything else here, for example:
server.get('/api/dosomething', function doSomething(req, res, next) // (server is an instance of a Restify server)
// use the db object here and so on
);
c) 每次需要时打开和关闭数据库? 示例:
// again, same as above
server.get('/api/something', function doSomething(req, res, next)
db.open(function(err, db)
// do something
db.close();
);
);
server.post('/api/somethingelse', function doSomethingElse(req, res, next)
db.open(function(err, db)
// do something else
db.close();
);
);
最后一个是我凭直觉会做的,但同时我也觉得这样做不太舒服。它不会对 Mongo 服务器造成太大压力吗?尤其是当(我希望我确实做到了)它会收到数百(如果不是数千)这样的电话吗?
提前谢谢你。
【问题讨论】:
此问题与***.com/q/10656574有关 【参考方案1】:我非常喜欢MongoJS。它允许您以与默认命令行非常相似的方式使用 Mongo,它只是官方 Mongo 驱动程序的包装。您只需打开数据库一次并指定您将使用的集合。如果您使用 --harmony-proxies
运行 Node,您甚至可以省略集合。
var db = require('mongojs').connect('mydb', ['posts']);
server.get('/posts', function (req, res)
db.posts.find(function (err, posts)
res.send(JSON.stringify(posts));
);
);
【讨论】:
我真的很喜欢它! :D 非常感谢。但是,就像我在回答的 cmets 中对 Gijs 所说的那样,我在某处读到,在同一连接下执行所有操作都会导致代码阻塞。你知道这是不是真的吗? 我不这么认为。它会破坏目的。我相信与数据库的连接是通过套接字完成的。套接字通过网络执行的操作与 Node 在使用 Streams 读取文件时执行的操作非常相似。 ReadStream 以小块的形式读取文件并在接收到它们时触发事件。我认为套接字对网络块也是如此。见nodejs.org/api/net.html#net_class_net_socket 阻塞或非阻塞取决于 API。所以上面的例子看起来像是阻塞的,因为server.get(...)
在你成功连接到数据库之前不会被执行(这纯粹是它的样子;我不熟悉 MongoJS)。但是,鉴于您可能需要数据库来执行任何事情,这并不一定那么糟糕,尽管如果您有许多需要很长时间才能执行的依赖项,那么最好使用具有期货/承诺/回调的解决方案,例如 @scttnlsn 的解决方案。
请注意,MongoJS 的实际查询实现似乎是异步的,从我从 github 页面可以看出,因为它们都采用回调参数,所以那里不应该有任何问题。【参考方案2】:
选项 A 不是一个好主意,因为无法保证在处理 HTTP 请求之前数据库将完成打开(当然这不太可能)
选项 C 也不理想,因为它不必要地打开和关闭数据库连接
我喜欢处理这个问题的方式是使用延迟/承诺。 Node 有很多不同的 Promise 库,但基本的想法是做这样的事情:
var promise = new Promise();
db.open(function(err, db)
// handle err
promise.resolve(db);
);
server.get('/api/something', function doSomething(req, res, next)
promise.then(function(db)
// do something
);
);
我相信 Mongoose 处理连接的方式与此类似。
【讨论】:
谢谢。我调查了 Mongoose,显然它与官方驱动程序并没有太大的不同。它只是在完成打开连接时触发一个事件,当它未连接时它会缓冲操作,因此您不必担心它。不过,我会研究一下承诺的事情:) 下面介绍的 MongoJS 库实际上是使用 Promise 的一个更好的例子(虽然它们被称为期货)。以上是关于Node.js 上 MongoDB 连接的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章
最佳实践 beanstalkd (queue) 和 node.js