我正在努力了解如何在节点应用程序中维护mongo客户端。我的第一个想法是为每一个收藏检索创建一个客户端。类似这样的东西:
const getCollection = (collectionName) => {
return MongoClient.connect(url, {useNewUrlParser: true, useUnifiedTopology: true})
.then((client) => {
const database = client.db(databaseName);
return database.collection(collectionName);
})
.catch((err) => {
console.log(err);
});
};
然后使用返回的promise进行查询。像这样:
const executeFind = (collectionName, query, projection, skip, limit) => {
return getCollection(collectionName)
.then(collection => {
return collection.find(query, {projection: projection})
.skip(skip)
.limit(limit)
.toArray();
})
.catch((err) => {
console.log(err);
});
};
这种方法的问题是,在运行应用程序时,与mongo的开放连接数量迅速增加,导致数据库操作出现问题,并发出大量警报。
我认为连接增加的可能原因:
- 大池大小-我尝试将
maxPoolSize=5
添加到URL。还将poolSize: 5
添加到options
(MongoClient的connect
函数的第二个参数。连接数仍然会爆发 - 缺少连接关闭-我现在找不到文档,但我在某个地方读到连接是由客户端自己管理的,所以不需要考虑使用
close()
。但无论如何,我试图在collection.find()
返回结果后将代码重写为客户端close()
。我得到Cannot use a session that has ended
除此之外,我没有任何其他想法来以一种在资源分配/运行方面高效的方式维护mongo客户端。我想听听两者的答案:
- 1.在这种方法中,究竟可以做些什么来避免开放连接的增加
- 2.维护mongo客户端的更通用/最佳/最佳实践方式是什么
- 检查下面的mongo-db池连接片段
MongoClient.connect(url, {
poolSize: 10
// other options can go here
}, function(err, db) {
global.mongodb = db;
});
- 为了处理连接,我们需要编写自定义代码,比如检查连接是否存在,如果不创建新的连接
我可以部分回答我的问题。我能够用client.close()
解决连接增加的问题。主要问题似乎是promise缺少await
,因此close()
导致了意外行为(close()
有时发生在实际调用查询之前,并导致session already closed
错误(。
上述方法(每次调用都打开和关闭连接(的问题在于速度相当慢。
仍在寻找最佳维护客户的一般答案
更新
我终于找到了一个解决方案,它不会打开高得离谱的连接,而且也是最优的。
这里的技巧是在数据访问层(或者数据库代码所在的任何地方(声明并调用异步函数,该函数将设置数据库对象。类似这样的东西:
let database;
(async () => {
const client = await MongoClient.connect(url, {poolSize: 150, useNewUrlParser: true, useUnifiedTopology: true});
database = client.db(databaseName);
})();
然后在任何地方重复使用数据库对象,如下所示:
database.collection(collectionName).insertMany(documents);
池和连接打开/关闭由client
处理。就最优性而言,它要快得多(正如预期的那样(。不确定在dao中调用全局数据库或立即函数(尽管,由于文件是用require
导入的,所以不应该多次调用(是否是最佳做法,但它确实做到了。