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
また、多くのクライアントが明示的なクローズなしでシャットダウンした場合、それらを検出してクローズするのに 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);
})
}
})
})