关于generic-pool与mongodb的性能问题
发布于 12 年前 作者 bao2dan 7006 次浏览 最后一次编辑是 8 年前
var poolModule = require('generic-pool');
exports.pool = poolModule.Pool({
    name     : 'mongo',
    create   : function(callback) {
        dbutil.createMongoClient('mongodbtest', function(err, db, client){
            callback(err,client);
        });
    },
    destroy  : function(client) {
      client.close();
    },
    max      : 10,
    idleTimeoutMillis :30000,
    log : false
});.

===============================================

var server_options = {
    auto_reconnect: true
},  
db_options = {
    native_parser: true,
    strict: false,
    safe: false
};
var mongo = require("mongodb"),
Server = mongo.Server,
var mongoServer = new mongo.Server('192.168.0.2', 27017,server_options);
{
    dbName : '',
    db : null,
    err:null,
    createMongoClient : function(dbname, callback){
        this.dbName = dbname;
        if(this.db == null){
            this.db = new mongo.Db(this.dbName,mongoServer , db_options);
        }
        this.db.open(function(err,db){
            this.db = db;
            this.err = err;
            if(callback) callback(this.err,this.db,dbutil);
        });
    }
}

为什么上面这个配置,1000并发60秒,会出现请求没有什么响应(之前还出现过: db object already connecting, open cannot be called multiple times); 当我把操作mongodb的代码注释后, 1000并发,30分钟都没有任何问题;

我也测过: max : 1, idleTimeoutMillis :300,

max      : 1,
idleTimeoutMillis :3000,

max      : 5,
idleTimeoutMillis :300,

等等…

2 回复

有两点可疑的。 1.从代码上下文和dbutil这个命名方式来推测,dbutil应该是一个全局性的唯一实例或者它指向的是一个模块。pool的create函数返回的正是dbutil,那么让连接池管理一个全局性实例合适吗。无论create/destroy多少次,用的同一个dbutil里面的db。无论并发多少,能用的数据库连接都只有一个。更糟糕的是,n个请求对同一个db进行open操作(想象n个人争着开同一扇门)。db object already connecting的警告信息很可能就是由此而来。根据generic-pool的文档,create返回对象一般来说应该是数据库连接本身。。。

2.闭包(Closure)回调函数中this的误用

this.db.open(function(err,db){
    this.db = db;
    this.err = err;
    if(callback) callback(this.err,this.db,dbutil);
});

上面代码中的第一个this和后续的this完全不是同一个对象,虽然它们都叫this。常见的解决方法2个

this.db.open(function(err,db){
    this.db = db;
    this.err = err;
    if(callback) callback(this.err,this.db,dbutil);
}.bind(this));

var self=this;
this.db.open(function(err,db){
     self.db = db;
     self.err = err;
     if(callback) callback(self.err,self.db,dbutil);
});

当然,也有可能楼主的意图是在回调函数里面生成一个新对象,然后,然后就不是某家所能臆测的了

dbutil 就是一个mongodb操作的模块,

<<<无论create/destroy多少次,用的同一个dbutil里面的db。无论并发多少,能用的数据库连接都只有一个。更糟糕的是,n个请求对同一个db进行open操作(想象n个人争着开同一扇门)。>>>>

这样会导致数据库连接中有一个?
我有点不疑问,不知道对不对,因为我把下面的参数调成这个后,出现这个问题的现象就当很多了: max : 50, idleTimeoutMillis :30000,

把mongodb的find insert 等封装起来,很多人都在这么干啊…

回到顶部