AWS Lambda Container销毁事件

时间:2017-07-21 10:03:23

标签: node.js containers aws-lambda serverless-framework

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

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

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

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

1 个答案:

答案 0 :(得分:16)

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

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

原始答案:

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

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

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

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);
    }
  });
};

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

我还看到了对话like this one,讨论了将连接置于主函数体外的可能性:

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);
    }
  });
};

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

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

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