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

koa: mongodb/redis active connection count ever-increasing

我正在使用中间件像这样传递我的 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;
};

yield 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);

yield 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 client/mongodb 客户端的简单示例吗?

我最好保留像上面那样捕获连接错误的能力,这样我的 node.js 应用程序就不会因为我的数据库关闭而关闭。

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

原来问题很明显。

而不是这个:

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

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