我使用10gen的本机node.js驱动器一起尝试使用mongodb(2.2.2)的node.js.
起初一切都很顺利.但是当进入并发基准测试部分时,发生了很多错误.经常连接/关闭1000个并发可能会导致mongodb拒绝任何进一步的请求,如下所示:
Error: failed to connect to [localhost:27017]
Error: Could not locate any valid servers in initial seed list
Error: no primary server found in set
Run Code Online (Sandbox Code Playgroud)
此外,如果许多客户端在没有显式关闭的情况下关闭,则需要mongodb分钟才能检测并关闭它们.这也会导致类似的连接问题.(使用/var/log/mongodb/mongodb.log检查连接状态)
我已经尝试了很多.根据手册,mongodb没有连接限制,但poolSize选项似乎对我没有影响.
由于我只在node-mongodb-native模块中使用它,我不太确定最终导致问题的原因.其他语言和驱动程序的性能如何?
PS:目前,使用自维护池是我想出的唯一解决方案,但使用它无法解决副本集的问题.根据我的测试,副本设置似乎比独立的mongodb少得多.但不知道为什么会这样.
并发测试代码:
var MongoClient = require('mongodb').MongoClient;
var uri = "mongodb://192.168.0.123:27017,192.168.0.124:27017/test";
for (var i = 0; i < 1000; i++) {
MongoClient.connect(uri, {
server: {
socketOptions: {
connectTimeoutMS: 3000
}
},
}, function (err, db) {
if (err) {
console.log('error: ', err);
} else {
var col = db.collection('test');
col.insert({abc:1}, function (err, result) {
if (err) {
console.log('insert error: ', err);
} else {
console.log('success: ', result);
}
db.close()
})
}
})
}
Run Code Online (Sandbox Code Playgroud)
通用池解决方案:
var MongoClient = require('mongodb').MongoClient;
var poolModule = require('generic-pool');
var uri = "mongodb://localhost/test";
var read_pool = poolModule.Pool({
name : 'redis_offer_payment_reader',
create : function(callback) {
MongoClient.connect(uri, {}, function (err, db) {
if (err) {
callback(err);
} else {
callback(null, db);
}
});
},
destroy : function(client) { client.close(); },
max : 400,
// optional. if you set this, make sure to drain() (see step 3)
min : 200,
// specifies how long a resource can stay idle in pool before being removed
idleTimeoutMillis : 30000,
// if true, logs via console.log - can also be a function
log : false
});
var size = [];
for (var i = 0; i < 100000; i++) {
size.push(i);
}
size.forEach(function () {
read_pool.acquire(function (err, db) {
if (err) {
console.log('error: ', err);
} else {
var col = db.collection('test');
col.insert({abc:1}, function (err, result) {
if (err) {
console.log('insert error: ', err);
} else {
//console.log('success: ', result);
}
read_pool.release(db);
})
}
})
})
Run Code Online (Sandbox Code Playgroud)
Hec*_*rea 23
由于Node.js是单线程的,因此您不应该在每个请求上打开和关闭连接(就像在其他多线程环境中那样).
这是编写MongoDB node.js客户端模块的人的引用:
"当你的应用程序启动并重用db对象时,你打开一次MongoClient.connect.它不是单独的连接池,每个.connect都会创建一个新的连接池.因此,一旦[d]重复使用所有请求,请打开它." - christkv https://groups.google.com/forum/#!msg/node-mongodb-native/mSGnnuG8C1o/Hiaqvdu1bWoJ