1. mongodb 的连接数问题
每次接受一个请求,打开数据库,然后将其关闭。像下面这样:
1
2
3
4
5
6
7
8
app.get('/detail/:id' ,function (req,res) {
MongoClient.connect('mongodb://127.0.0.1:27017/test' , function (err, db) {
db.findOne({_id:ObjectId(req.params.id)},function (err,result) {
db.close()
})
});
})
直觉有点浪费,每次 request 都重新建立 db connection,用完后又关掉,对于高并发的应用来说,尤其浪费。
所以,更好的方式是复用db connection,以下代码摘自 mongodb node native 官方例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var express = require ('express' );
var mongodb = require ('mongodb' );
var app = express();
var MongoClient = require ('mongodb' ).MongoClient;
var db;
MongoClient.connect("mongodb://localhost:27017/integration_test" , function (err, database) {
if (err) throw err;
db = database;
app.listen(3000 );
console.log("Listening on port 3000" );
});
app.get("/" , function (req, res) {
db.collection("replicaset_mongo_client_collection" ).find({}, function (err, docs) {
docs.each(function (err, doc) {
if (doc) {
console.log(doc);
}else {
res.end();
}
});
});
});
应用初始化时,就建立一个 db 实例,以后所有的连接,都是使用这个 db connection。
并且,通过上面方式建立的 db connection 单独的连接,而是 connection pool,非常高效。
You open do MongoClient.connect once when your app boots up and reuse the db object. It’s not a singleton connection pool each .connect creates a new connection pool. [4]更进一步,API 还提供了 maxPoolSize 选项,设置连接池的最大值,默认为 5
http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html ### 2. mongodb 连接失败导致 node crash
见 stackoverflow 上的问题 How to ensure Node.js keeps running after MonogBD connection drops? [1],如何让 Node.js 在数据库挂掉后继续跑? 目前没有特别好的解决方案。
首先描述下问题,创建一个 mongodb client:
1
2
3
MongoClient.connect('mongodb://127.0.0.1:27017/test' , function (err, db) {
});
当db连接断掉后(可以手动kill掉mongod进程来模拟复现当掉的情况),再访问 web 服务,就会出现下面类似的出错:
1
Error : failed to connect to [localhost:27017 ]
这时候web服务也宕掉了……
理想的情况是,希望出现一个 500 内部错误提示界面,或者提示在升级什么的,但是数据库连接断掉以后,(我猜测)是 throw 了一个 Error 出来,导致 Node 的主进程挂掉了
其中一个解决方案是,将数据库的连接操作放在 domain 中。
1
2
3
4
5
6
7
8
9
10
var d = require ('domain' ).create();
d.on('error' , function (er) {
console.log('Oh no, something wrong with DB' );
});
d.run(function () {
mongoose.connect(config.db, options);
});
domain 的介绍见 文档 http://nodejs.org/api/domain.html, 不过,有点要注意就是 domain 还不够稳定 ,文档标注的是 unstable
, 不过,附录[1] 说已经用于生产环境中了,并且没有发现啥问题。
3. 总结:数据库连接可以复用;为保证数据库挂掉后,Node.js 主进程仍然继续跑,可以将数据可的连接操作放到 domain
模块中
4. 附录:mongolab 上的一篇博文 Deep Dive into Connection Pooling [3]
参考
[1] http://stackoverflow.com/questions/20689768/how-to-ensure-node-js-keeps-running-after-monogbd-connection-drops/20690008#20690008
[2] http://stackoverflow.com/questions/10656574/how-to-manage-mongodb-connections-in-a-nodejs-webapp
[3] http://blog.mongolab.com/2013/11/deep-dive-into-connection-pooling/ 介绍两种数据库连接方式,一种复用(好),一种不复用(坏)
[4] https://groups.google.com/forum/#!msg/node-mongodb-native/mSGnnuG8C1o/Hiaqvdu1bWoJ