如何在lambda函数中正确关闭数据库连接?

问题描述 投票:0回答:5

在我的 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 });
};

知道如何解决这个问题吗?此时我们真的必须关闭连接吗?

lambda aws-lambda serverless-framework
5个回答
12
投票

mongoose.connect
代码移至处理程序内,或停止调用
db.close()
。您当前有一个数据库连接被 Lambda 函数的多次调用重复使用,但您将在第一次调用完成后关闭它。


3
投票

Lambda 将在每次调用中执行您的handleCreateUser 函数,但handleCreateUser 之外的所有内容将仅在冷启动时执行。 Lambda 将缓存该值以供进一步调用,并且不会执行

mongoose.connect(process.env.DATABASE_URL);

在每次调用中。所以我认为你应该将此代码移动到handleCreateUser函数中。


1
投票

我使用的是 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 位于内存中时,你会一直保持连接。

我认为这是值得的。


0
投票

如果您在处理程序外部创建数据库连接,它将在 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)
});

-5
投票

可以尝试 try-with-resource 它会自动关闭连接。

© www.soinside.com 2019 - 2024. All rights reserved.