Ava*_*iya 11 connection-pooling mongoose mongodb node.js aws-lambda
我们使用 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;
}
}
Run Code Online (Sandbox Code Playgroud)
相同的连接可以跨 Lambda 使用吗?有办法做到吗?
您应该在 AWS Lambda 处理程序函数之外定义 MongoDB 服务器的客户端。不要在每次调用函数时都定义新的 MongoClient 对象。这样做会导致驱动程序在每次函数调用时创建一个新的数据库连接。这可能成本高昂,并且可能导致您的应用程序超出数据库连接限制。
作为替代方案,请执行以下操作:
将对函数的调用隔离MongoClient.connect()
到其自己的模块中,以便可以跨函数重用连接。让我们mongo-client.js
为此创建一个文件:
mongo-client.js:
const { MongoClient } = require('mongodb');
// Export a module-scoped MongoClient promise. By doing this in a separate
// module, the client can be shared across functions.
const client = new MongoClient(process.env.MONGODB_URI);
module.exports = client.connect();
Run Code Online (Sandbox Code Playgroud)
导入新模块并在函数处理程序中使用它来连接到数据库。
一些文件.js:
const clientPromise = require('./mongodb-client');
// Handler
module.exports.handler = async function(event, context) {
// Get the MongoClient by calling await on the connection promise. Because
// this is a promise, it will only resolve once.
const client = await clientPromise;
// Use the connection to return the name of the connected database for example.
return client.db().databaseName;
}
Run Code Online (Sandbox Code Playgroud)
连接池大小是维护的数据库连接的缓存,以便在将来需要向数据库发出请求时可以重用这些连接。连接池用于增强在数据库上执行命令的性能。
注意: maxPoolSize
和poolSize
是相同的,只不过它们与您是否正在使用该useUnifiedTopology: true
设置有关。如果您使用useUnifiedTopology: true
,maxPoolSize
是符合规范的设置来管理连接池的大小。但是,如果您正在使用useUnifiedTopology: false
(或省略它),则poolSize
是相同的事情,但在我们拥有统一拓扑之前。
注意:每个连接大约消耗 1MB RAM。
连接池以每个 mongod/mongos 为基础,因此当连接到 3 成员副本时,将存在三个连接池(每个 mongod 一个),每个连接池都有一个maxPoolSize
. 此外,每个节点还需要一个监控连接,因此最终会得到(maxPoolSize+1)*number_of_nodes
TCP 连接。
在我看来,如果你不关心 CPU 和 RAM,你应该使用所有可用的连接(如果我们已经有了它们为什么不呢,对吧?)。
例如:您有一个包含 3 个副本集的 Atlas 免费集群,最多支持 500 个连接,并且您只有一个应用程序连接到该集群,请将所有连接都分配给该一个应用程序。为了设置 的值poolSize
,您可以使用上面的连接计算:
poolSize = (maximum_connections/number_of_nodes) - 1
poolSize = (500/3) - 1
poolSize = 165
Run Code Online (Sandbox Code Playgroud)
如果您有 2 个应用程序将连接到同一集群,请为每个应用程序分配一半的连接。
如果您的 RAM 内存有限,请检查您可以使用多少内存并poolSize
据此进行计算(正如我在注释中所说,您可以假设一个连接将消耗大约 1MB 的 RAM)。
有关更多信息,请查看官方 MongoDB 文档。
归档时间: |
|
查看次数: |
3208 次 |
最近记录: |