我正在使用中间件来传递我的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:我主要使用yieldb
和then-redis
,因为他们的基于承诺的api,但使用本机驱动程序的示例也很好。
答案 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;
};
缓存了实例而不是创建更多实例(这反过来会打开更多连接)。