mongodbデータベースデバッグの問題:‘db object already connecting,open cannot be called multiple times’

6147 ワード

マイクロブログシステムのデバッグ中:
(1)ログインログインログインは正常に表示され、登録時にネットワーク接続が突然停止したが、ユーザー名とパスワードがデータベースに格納され、undefined is not a functionとエラーが発生した.
エラーは主にUseを指す.jsの一言:mongodb.close();
ソリューション:mongodbバージョンは1.3.0より高いため、mongodbと考えられます.close()この関数は定義されていないので関数として使用し、mongodbを直接使用します.close()という言葉の注釈を外すと、システムは正常に登録して実行することができます.
(2)mongodbを注釈する.close()以降mongodbでよく発生するエラーdb object already connecting,open cannot be called multiple times’
Nodejsは非同期スレッドであり、いずれにしてもdbを用いる.Open()ですが、データベースを開くたびにアクセスが完了するたびに、パンツdbを閉じる必要があります.close();
前のデバッグでデータベースのシャットダウンを注記すると、データベースは常に開いていて、データベースがまだ閉じていないのにここで開くとdb object already connecting、open cannot be called multiple times'のエラーが発生します.
この時点でのソリューション:
a:データベースが開く前にmongodbを直接前に追加します.close()は、データベースが開くたびにデータベースが閉じられ、デバッグされたシステムが正常に動作していることを確認します.
b.open and close動作からopen once and reuse anywhereに変更します.プログラムが起動するとdb.Openは一度にhttpリクエストごとにデータベースに直接アクセスし、dbを破棄する.open/db.closeという2つの余計な操作
元のopen+closeメソッド:
var server_options={};

var db_options={w:-1};



var mongodb = require("mongodb"),

    mongoserver = new mongodb.Server('localhost', 27017,server_options ),

    db = new mongodb.Db('test', mongoserver, db_options);



var http=require('http');



var server=http.createServer(function(req,res){

    db.open(function(err,db){

        if(err)return console.error(err);

        console.log('* mongodb connected');

        db.collection('foo').save({test:1},function(err,result){

            res.end(JSON.stringify(result,null,2));

            db.close();

        });

    })



});

server.listen(8080,function(){

    console.log('server listen to %d',this.address().port);

});

setTimeout(function(){

    //http.get('http://localhost:8080',function(res){console.log('request ok')});

    //http.get('http://localhost:8080',function(res){console.log('request ok')});

},2000);


dbを捨てるopen/db.closeという2つのループに対応した操作の方法で,最初から開いている状態にする.
var server_options={'auto_reconnect':true,poolSize:5};

var db_options={w:-1};



var mongodb = require("mongodb"),

    mongoserver = new mongodb.Server('localhost', 27017,server_options ),

    db = new mongodb.Db('test', mongoserver, db_options);



db.open(function(err,db){

    if(err)throw err;

    console.info('mongodb connected');

});

var http=require('http');



var server=http.createServer(function(req,res){

    db.collection('foo').save({test:1},function(err,result){

        res.end(JSON.stringify(result,null,2));

    });



});

server.listen(8080,function(){

    console.log('server listen to %d',this.address().port);

});

setTimeout(function(){

    http.get('http://localhost:8080',function(res){console.log('request ok')});

    http.get('http://localhost:8080',function(res){console.log('request ok')});

},2000); 

このように変更すると、同時アクセス>5の場合、同時に使用可能な最下位のデータベース接続が5しかないため、ブロックが発生する可能性があります.
実際にシーンを適用する場合、dbオブジェクトを直接参照するのは良いアイデアではありません.デフォルトでは、dbのpoolSize=5は、同時性が5しかないことを意味しますが、同時性を高めるにはpoolSizeを10に引き延ばしますか?20? 50? 100? NO,我々に必要なのは接続数を動的に調整できる接続プールであり,ピーク時の接続数の要求を満たすだけでなく,mongodbの内蔵接続プールのように固定接続数を維持するのではなく,空き期間にアイドル接続を解放することができる.どうしよう?車輪を再発明しますか?いいえ、既存の接続プールモジュールgenericを再利用します.pool、コードは以下の通りです
var http=require('http'),

    mongodb = require("mongodb"),

    poolModule = require('generic-pool');



var pool = poolModule.Pool({

    name     : 'mongodb',

    create   : function(callback) {

        var server_options={'auto_reconnect':false,poolSize:1};

        var db_options={w:-1};

        var mongoserver = new mongodb.Server('localhost', 27017,server_options );

        var db=new mongodb.Db('test', mongoserver, db_options);

        db.open(function(err,db){

            if(err)return callback(err);

            callback(null,db);

        });

    },

    destroy  : function(db) { db.close(); },

    max      : 10,//              

    idleTimeoutMillis : 30000,

    log : false 

});



var server=http.createServer(function(req,res){

    pool.acquire(function(err, db) {

        if (err) {

            res.statusCode=500;

            res.end(JSON.stringify(err,null,2));

        } else {

            db.collection('foo').save({test:1},function(err,result){

                res.end(JSON.stringify(result,null,2));

                pool.release(db);

            });

        }

    });

});

server.listen(8080,function(){

    console.log('server listen to %d',this.address().port);

});

setTimeout(function(){

    http.get('http://localhost:8080',function(res){console.log('request ok')});

    http.get('http://localhost:8080',function(res){console.log('request ok')});

},2000);


c.mongodbデータベースに対して1つの問題があります:リフレッシュが速すぎて、あるいは複数のユーザーが同時にデータベースにアクセスして、データベースが閉じる暇がなくて、db object already connecting、open cannot be called multiple timesというエラーが発生します
mongoseを使用すると、mongoseではデータベースに接続するとdbがopen状態になり、アクセス時に開くルールがなく、閉じるルールがないため、mongoseを使用するとこのエラーは発生しません.
これはmongodbの操作方法です.
User.get = function get(username, callback) {

  mongodb.open(function(err, db) {

    if (err) {

      return callback(err);

    }

    //   users   

    db.collection('users', function(err, collection) {

      if (err) {

        mongodb.close();

        return callback(err);

      }

      //   name     username    

      collection.findOne({name: username}, function(err, doc) {

        mongodb.close();

        if (doc) callback (err, doc);

        else callback (err, null);

      });

    });

  });

};


これはmongoseでの操作方法です
User.get = function get(username, callback) {

  users.findOne({name:username}, function(err, doc){

    if (err) {

      return callback(err, null);

    }

    return callback(err, doc);

  });

};


  
以上a.b.cはdb object already connecting,open cannot be called multiple times’問題を解決するための3つのスキームのまとめである