21

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);
            })
        }
    })
})
4

2 に答える 2

23

Node.js はシングル スレッドであるため、リクエストごとに接続を開いたり閉じたりする必要はありません (他のマルチスレッド環境で行うように)。

これは、MongoDB node.js クライアント モジュールを作成した人物からの引用です。

「アプリの起動時に do MongoClient.connect を 1 回開き、db オブジェクトを再利用します。.connect ごとに新しい接続プールが作成されるのは、シングルトン接続プールではありません。一度開くと、[d] すべてのリクエストで再利用できます。」-christkv https://groups.google.com/forum/#!msg/node-mongodb-native/mSGnnuG8C1o/Hiaqvdu1bWoJ

于 2013-03-28T17:41:40.870 に答える