我们使用的是Mongoose、Nodejs、Serverless和AWS Lambda。为了使用同一个连接,而不是每次都打开和关闭连接,我创建了一个大小为10的连接池(对于我们现在的用例来说似乎已经足够了)。
但问题是,当我看到Lambda的Cloudwatch日志时,它与正在使用的连接并不相同。
- 每次调用一个新的Lambda时,都会创建一个新的连接,而对该Lambda的后续调用使用第一次调用中打开的相同连接。*
导致一次打开的连接数量增加。在MongoDB Atlas上,我可以看到打开的连接数量非常多。
下面是我在没有缓存连接可用时创建连接的代码。如果缓存连接可用,将使用缓存连接,而不会创建新连接。
let cached_db;
exports.createConnection = async () => {
if(cached_db == null){
return await mongoose.connect(
connection_uri,
{ 'useUnifiedTopology': true ,
'useNewUrlParser': true,
'useFindAndModify': false ,
'useCreateIndex': true,
'socketTimeoutMS': 60000,
'connectTimeoutMS': 60000,
'poolSize': 10
}
).then(conn => {
cached_db = conn;
return conn;
}).catch((err) => {
console.error('Something went wrong', err);
throw err;
});
} else {
console.log("Cached db in use.");
return cached_db;
}
}
相同的连接可以跨Lambda使用吗?有没有办法做到?
2条答案
按热度按时间disbfnqx1#
您应该在AWS Lambda处理函数之外定义MongoDB服务器的客户端。不要在每次调用函数时都定义一个新的MongoClient对象。这样做会导致驱动程序在每次函数调用时创建一个新的数据库连接。这可能会导致开销很大,并可能导致您的应用程序超出数据库连接限制。
或者,执行以下操作:
1.创建MongoClient对象一次。
1.存储该对象,以便您的函数可以跨函数调用重用MongoClient。
步骤1
将对
MongoClient.connect()
函数的调用隔离到它自己的模块中,这样连接就可以在函数之间重用,让我们为此创建一个文件mongo-client.js
:步骤2
导入新模块并在函数处理程序中使用它来连接到数据库。
样本池大小
连接池大小是维护的数据库连接的高速缓存,以便将来需要对数据库发出请求时可以重用这些连接。连接池用于提高在数据库上执行命令的性能。
maxPoolSize
和poolSize
是相同的,除了它们与您是否使用useUnifiedTopology: true
设置有关。如果您使用useUnifiedTopology: true
,maxPoolSize
是规范兼容的设置,用于管理连接池的大小。但是如果您使用useUnifiedTopology: false
(或省略它),poolSize
是相同的,但在我们使用统一拓扑之前。池大小的值
连接池是以mongod/mongos为基础的,因此当连接到一个3成员副本时,将有三个连接池(每个mongod一个),每个连接池都有一个
maxPoolSize
。此外,每个节点还需要一个监视连接,因此您最终会得到(maxPoolSize+1)*number_of_nodes
TCP连接。在我看来,如果你不关心CPU和RAM,你应该使用所有可用的连接(如果我们已经有了,为什么不呢?)
poolSize
的值,您可以使用以上连接计算:如果有2个应用程序将连接到同一个集群,请为每个应用程序分配一半的连接。
如果您的RAM内存有限,请检查您可以使用多少内存,并基于此计算
poolSize
(正如我在注解中所说的,您可以假设一个连接将消耗大约1MB的RAM)。资源
有关详细信息,请查看this official MongoDB Docs。
对于连接池,请选中this和this。
yiytaume2#
我从this blog中发现,如果恢复相同的快照,Lambda可能会使用相同的连接,如果生成新快照,Lambda可能会创建新连接。
所以如果我们在句柄函数之外使用,Lambda不能保证使用相同的连接。
所以在我看来,优化Mongodb连接数量的最佳方法是在lambda完成之前关闭连接,这样你的其他服务就可以使用免费连接。
使用以下方法在数据库交互完成后关闭连接。