AWS Lambda RDS连接超时
我正在尝试使用连接到我的RDS数据库的Node.js编写一个Lambda函数。 数据库正在工作,可以从我的Elastic Beanstalk环境访问。 当我运行该函数时,它返回一个超时错误。
试图增加超时到5分钟,完全相同的结果。
经过一番研究,我得出的结论是,这可能是一个安全问题,但无法在亚马逊的文档或这个答案中find解决scheme(这是我能find的唯一的答案)。
以下是安全细节:
- RDS和Lambda都在同一个安全组中。
- RDS具有所有stream量入站和出站规则。
- 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'); }); };
我得到的结果是:
"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"
我要感谢所有帮助过我的人,这个问题与我想象中的不同。 由于某些原因,代码中的callback
不起作用,即使它在AMAZON'S OWN DEFAULT SAMPLE中。
工作代码如下所示:
'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'); }); };
虽然使用上下文将工作,你只需要添加context.callbackWaitsForEmptyEventLoop = false;
到处理程序,然后像这样正常使用callback:
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'); }); };
答案在这里的文档(花了我几个小时find这个): http : //docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html
在“比较上下文和callback方法”一节中,有一个“重要”注释来解释事情。
在笔记底部写着:
因此,如果需要与上下文方法相同的行为,则必须将上下文对象属性callbackWaitsForEmptyEventLoop设置为false。
基本上,callback继续到事件循环的结尾,而不是结束事件循环的上下文。 所以设置callbackWaitsForEmptyEventLoop使callback像上下文一样工作。
我连接RDS时分享我的经验。
您需要为
Lambda function
启用VPC
访问,在此期间您将为其分配安全组 。
然后,在分配给RDS实例的安全组内,您将为分配给Lambdafunction的安全组启用访问。
你可以在这里获得更多的信息
RDS和Lambda都在同一个安全组中。
这是关键。 默认情况下,同一个安全组内的通讯是不允许的。 而且你需要明确的允许它(Ex sg-xxxxx ALL TCP)。 这只会工作,如果你的lambda试图通过私人IP访问数据库。
如果它试图通过公共IP访问它,它将无法正常工作,并且您还需要为此添加必要的整体。
但有更好的办法:
- 为您的lambda创build单独的安全组
- 在RDS sg的端口
3306
允许入站stream量为lambdas sg。
这个问题并不是来自超时,而是来自你closures连接的方式。 使用.destroy()
而不是等待callback,或者在closures.end(function(err) { //Now call your callback });
的连接时正确使用callback.end(function(err) { //Now call your callback });
看到这个线程更深入的解释。
- 如何dynamic设置快递服务器的端口?
- 如何创build一个从HTTP / HTTPS API获取数据的Alexa Skill(在AWS Lambda上使用Node.js的“Alexa技能工具包”)