AWS Lambda Container销毁事件

Vis*_*nan 15 containers node.js aws-lambda serverless-framework

何时释放lambda中的连接和清理资源.在普通的Node JS应用程序中,我们使用钩子

process.on('exit', (code) => {
    console.log(`About to exit with code: ${code}`);
});
Run Code Online (Sandbox Code Playgroud)

但是,这不适用于AWS Lambda.导致睡眠模式下的Mysql连接.我们没有足够的资源用于此类活动连接.AWS文档均未指定实现此目的的方法.

如何接收AWS Lambda容器的停止事件?

Tod*_*ice 16

编辑:简短的回答是没有这样的事件知道容器何时停止.

中等答案:在与AWS的某个人谈论此事后,我现在认为您应该在模块级别对数据库连接进行范围调整,以便只要容器存在就可以重用它们.当您的容器被销毁时,该连接将被销毁.

原始答案:

这个问题触及了AWS Lambda函数需要考虑的一些相当复杂的问题,主要是因为可以考虑连接池或与数据库的长期连接.首先,Node.js中的Lambda函数作为单个导出的Node.js函数执行,具有此签名(您可能知道):

exports.handler = (event, context, callback) => {
    // TODO implement
    callback(null, 'Hello from Lambda');
};
Run Code Online (Sandbox Code Playgroud)

处理数据库连接的最简洁和最简单的方法是使用每个函数调用来创建和销毁它们.在这种情况下,将在函数开头创建数据库连接,并在调用最终回调之前将其销毁.像这样的东西:

const mysql = require('mysql');

exports.handler = (event, context, callback) => {
  let connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'me',
    password : 'secret',
    database : 'my_db'
  });

  connection.connect();

  connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
    if (error) {
      connection.end();
      callback(error);
    }
    else {
      let retval = results[0].solution;
      connection.end();
      console.log('The solution is: ', retval);
      callback(null, retval);
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

注意:我没有测试过该代码.我只是提供一个讨论的例子.

我也看过像这样的对话,讨论将连接放在主函数体外的可能性:

const mysql = require('mysql');

let connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'me',
  password : 'secret',
  database : 'my_db'
});

connection.connect();

exports.handler = (event, context, callback) => {
  // NOTE: should check if the connection is open first here
  connection.query('SELECT 1 + 1 AS solution', (error, results, fields) => {
    if (error) {
      callback(error);
    }
    else {
      let retval = results[0].solution;
      console.log('The solution is: ', retval);
      callback(null, retval);
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

这里的理论是这样的:因为AWS Lambda将在第一次调用函数后尝试重用现有容器,下一个函数调用将已经打开了数据库连接.上面的例子应该在使用之前检查是否存在打开的连接,但是你明白了.

问题当然是这会使你的连接无限期地打开.我不是这种方法的粉丝,但根据你的具体情况,这可能会奏效.您还可以在该方案中引入连接池.但无论如何,在这种情况下,您没有事件干净地破坏连接或池.托管您的功能的容器进程本身就会被杀死.所以你必须依靠你的数据库在某个时刻终止它的连接.

我对其中的一些细节可能是错的,但我相信你所处的高水平.希望有所帮助!

  • @ViktorMolokostov问题是关于如何接收Lambda容器的停止事件.答案是没有这样的事件. (4认同)
  • 我已经减去了这一点,因为"答案"没有提供何时关闭连接的任何解决方案. (2认同)
  • 我最近在 2020 年底对第一种方法和第二种方法之间的差异进行了一些性能评估,并且可以自信地说,在打开与 AWS RDS 上托管的 v12 Postgres 的数据库连接、读取一些数据并关闭连接的简单情况下,第一种方法和第二种方法之间的性能损失非常小。使用此答案中的第一种方法,在阅读之前打开连接,并在函数退出之前在finally中关闭连接。快速进行性能检查并完成!@维克托莫洛科斯托夫 (2认同)