我使用10gen的native node.js驅動器一起嘗試使用mongodb(2.2.2)的node.js。處理Mongodb連接的正確方法是什麼?
起初一切進展順利。但是當進入併發基準測試部分時,出現了很多錯誤。頻繁連接/接近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
而且,如果很多客戶關機沒有明確的密切,它會採取的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()
})
}
})
}
通用池溶液:
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);
})
}
})
})
雖然Node.js的使用一個單一的過程和事件模型,但IO動作應該永遠是異步。我認爲這可能不是我的問題的原因。但是,我會嘗試你引用的方式,謝謝。 – Jack
在第一個例子中,你錯過了這一點;該代碼相當於啓動您的Mongo應用1000次。您應該只在應用中調用.connect一次。 –
是的,這是問題,原因是MongoClient擁有一個連接池本身,它比其他dbs更昂貴。但不是node.js單一過程模型的問題。 – Jack