koa:mongodb / redis活动连接数不断增加

时间:2015-04-10 17:13:10

标签: node.js mongodb redis koa io.js

我正在使用中间件来传递我的mongodb / redis客户端实例:

function *middleware(next) {
    // allow downstream to handle db connection error gracefully
    try {
        this.db = yield mongodb.apply(this);
    } catch(err) {
        this.db = false;
        this.app.emit('error', err, this);
    }

    try {
        this.redis = yield redis.apply(this);
    } catch(err) {
        this.redis = false;
        this.app.emit('error', err, this);
    }

    yield next;
};

产生mongodb.apply(this),调用类似的东西。

// build server string
var url = 'mongodb://';

if (opts.user && opts.pass) {
    url += opts.user + ':' + opts.pass + '@';
}

// basic connection url
url += opts.server + ':' + opts.port
    + '/' + opts.database + '?w=' + opts.w;

if (opts.replSet) {
    url += '&replicaSet=' + opts.replSet;
}

if (opts.userdb) {
    url += '&authSource=' + opts.userdb;
}

// make sure we have active connection to mongodb
return yield mongo(url);

产生redis.apply(this),调用类似的东西。

var client = redis.createClient(opts);

// prevent redis error from crashing our app
client.on('error', function(err) {
    // you can log driver connection attempts here
});

// make sure we have active connection to redis
yield client.select(opts.database);

return client;

但是有了这种模式,我看到了与mongodb / redis不断增加的活动连接,最终达到了极限并阻止了驱动程序打开更多连接。

// for redis

# Clients
connected_clients:64
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

// for mongodb

"globalLock" : {
    "totalTime" : NumberLong("858671365000"),
    "currentQueue" : {
        "total" : 0,
        "readers" : 0,
        "writers" : 0
    },
    "activeClients" : {
        "total" : 329,
        "readers" : 0,
        "writers" : 0
    }
},

我最好的猜测是我没有正确使用客户端。有人能给我一个关于如何在koa上下文中正确重用redis客户端/ mongodb客户端的简单示例吗?

最好我想保留捕获连接错误的能力,所以我的node.js应用程序不会因为我的数据库关闭而停机。

PS:我主要使用yieldbthen-redis,因为他们的基于承诺的api,但使用本机驱动程序的示例也很好。

1 个答案:

答案 0 :(得分:0)

事实证明问题非常明显。

而不是:

function *database() {
    var client = yield mongo(this.mongo.url);

    return client;
};

我应该这样做;

var client;

function *database() {
    if (client) {
        return client;
    }

    client = yield mongo(this.mongo.url);

    return client;
};

缓存了实例而不是创建更多实例(这反过来会打开更多连接)。