在我的 lambda 函数中,我尝试在发送回调后立即关闭 mongo 连接。但它有一个问题。
db.close()
时,事情就完美了。我认为 lambda 重新使用了所有函数的连接,因为我在处理程序顶部打开了连接:
// Connect to database
mongoose.connect(process.env.DATABASE_URL);
const handleCreateUser = async (event, context, callback) => {
// eslint-disable-next-line no-param-reassign
context.callbackWaitsForEmptyEventLoop = false;
const data = JSON.parse(event.body);
const { user, userProfile } = data;
await createUser({ callback, user, userProfile });
};
知道如何解决这个问题吗?此时我们真的必须关闭连接吗?
将
mongoose.connect
代码移至处理程序内,或停止调用 db.close()
。您当前有一个数据库连接被 Lambda 函数的多次调用重复使用,但您将在第一次调用完成后关闭它。
Lambda 将在每次调用中执行您的handleCreateUser 函数,但handleCreateUser 之外的所有内容将仅在冷启动时执行。 Lambda 将缓存该值以供进一步调用,并且不会执行
mongoose.connect(process.env.DATABASE_URL);
在每次调用中。所以我认为你应该将此代码移动到handleCreateUser函数中。
我使用的是 Python,但您可以使用您喜欢的语言来执行此操作。考虑按次付费,lambda 的最佳解决方案: 在 lba 函数之前全局运行此函数(我在配置类中执行此操作)
if self.conn == None or self.conn.close == 1:
self.make_connection()
由您决定如何实现 make_connection()。 根本不要使用 db.close()。
AWS 调用加载您的 lambda 函数并运行一次全局函数。 之后,在每次调用时,它仅运行 lambda,并保持加载一段时间(从某些测试来看,为 20 分钟到 50 分钟)。 连接将由数据库驱动程序在内部超时时关闭。
优点 - 您只需在很长一段时间内打开一次连接,从而节省每次 lambda 运行的时间。
缺点 - 当 lambda 位于内存中时,你会一直保持连接。
我认为这是值得的。
如果您在处理程序外部创建数据库连接,它将在 Lambda 容器的
Init
阶段中设置。然后它可以被一次或多次调用使用(Invoke
阶段)。因此,关闭处理程序内的连接将导致以下调用具有不可用的关闭连接。
要正确关闭连接(而不是等待超时),您可以使用在容器关闭时触发的挂钩。从这里复制:
// SIGTERM Handler
process.on('SIGTERM', async () => {
console.info('[runtime] SIGTERM received');
console.info('[runtime] cleaning up');
// perform actual clean up work here.
await new Promise(resolve => setTimeout(resolve, 200));
console.info('[runtime] exiting');
process.exit(0)
});
可以尝试 try-with-resource 它会自动关闭连接。