AWS Lambda RDS连接超时

Sir*_*lot 18 rds amazon-web-services node.js aws-lambda

我正在尝试使用连接到我的RDS数据库的Node.js编写Lambda函数.数据库正在运行,可从我的Elastic Beanstalk环境访问.当我运行该函数时,它返回一个超时错误.

尝试使用完全相同的结果将超时增加到5分钟.

我在经过一些研究后得出的结论是,这可能是一个安全问题,但无法在亚马逊的文档或这个答案中找到解决方案(这是我唯一可以找到的主题).

以下是安全细节:

  • RDS和Lambda都在同一个安全组中.
  • RDS具有所有流量入站和出站规则.
  • Lambda的角色是AmazonVPCFullAccess策略.

我的代码是:

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context, callback) => {

   var connection = mysql.createConnection({
        host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) callback(null, 'error ' +err);
      else callback(null, 'Success');
    });

};
Run Code Online (Sandbox Code Playgroud)

我得到的结果是:

"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"
Run Code Online (Sandbox Code Playgroud)

小智 26

虽然使用上下文将起作用,您只需要添加context.callbackWaitsForEmptyEventLoop = false;到处理程序然后像往常一样使用回调:

exports.handler = (event, context) => {
  context.callbackWaitsForEmptyEventLoop = false; 
  var connection = mysql.createConnection({
    //connection info
  });
  connection.connect(function(err) {
    if (err) callback(err); 
    else callback(null, 'Success');
  });
};
Run Code Online (Sandbox Code Playgroud)

答案就在文档中(花了几个小时才发现):http: //docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html

在"比较上下文和回调方法"一节中,它有一个解释事物的"重要"注释.

在笔记的底部写着:

因此,如果您希望与上下文方法具有相同的行为,则必须将上下文对象属性callbackWaitsForEmptyEventLoop设置为false.

基本上,回调继续到事件循环的结束,而不是结束事件循环的上下文.因此,设置callbackWaitsForEmptyEventLoop会使回调像上下文一样工作.

  • 传奇!谢谢,这是正确答案:context.callbackWaitsForEmptyEventLoop = false; (2认同)

Sir*_*lot 11

我要感谢所有帮助的人,问题结果与我想的不同.该callback代码不会因为即使是在亚马逊自己的默认采样某些原因.

工作代码如下所示:

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context) => {

   var connection = mysql.createConnection({
        host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) context.fail();
      else context.succeed('Success');
    });

};
Run Code Online (Sandbox Code Playgroud)

  • 遇到这个答案 - 只是想指出回调参数是可选的,具体取决于您的 NodeJS 版本,根据 AWS 文档:https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-模型处理程序.html (2认同)

Vor*_*Vor 5

RDS和Lambda都在同一安全组中。

那是关键。默认情况下,不允许在同一安全组内进行通信。并且您需要明确允许它(例如sg-xxxxx ALL TCP)。仅当您的lambda尝试通过私有ip访问数据库时,此方法才会起作用。

如果它尝试通过公共IP访问它,它将无法正常工作,并且您还需要为此打出必要的整体。

但是有更好的方法:

  1. 为您的lambda创建单独的单独的安全组
  2. 3306在RDS SG中的lambdas sg中允许端口上的入站流量。

  • 救生员。谁会想到AWS默认会阻止同一安全组内的通信?没有AWS教程提到这一点,很显然您需要将Lambda和RDS放在同一个组中,但是没有提及您需要使它们能够通信。(我的首选方法是添加一个InBound规则,以允许来自同一安全组中的所有TCP流量,但是建议为Lambda创建一个新规则并将其启用当然也可以。) (2认同)