AWS Lambda RDS 连接超时
AWS Lambda RDS connection timeout
我正在尝试使用连接到我的 RDS 数据库的 Node.js 编写 Lambda 函数。数据库正在运行并且可以从我的 Elastic Beanstalk 环境中访问。当我 运行 函数时,它 returns 超时错误。
尝试将超时增加到 5 分钟,结果完全相同。
我经过一些研究得出的结论是,这可能是一个安全问题,但无法在亚马逊的文档或 this 答案中找到解决方案(这是我能找到的关于该主题的唯一答案) ).
以下是安全详细信息:
- 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');
});
};
我得到的结果是:
"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"
我正在分享我连接RDS的经验。
You need to enable VPC
access for the Lambda function
, during which you will assign it a Security Group.
然后,在分配给 RDS 实例的安全组中,您将为分配给 Lambda 函数的安全组启用访问权限。
您可以获得更多信息here
Both the RDS and the Lambda are in the same security group.
这是关键。默认不允许同一个安全组内的通信。并且您需要明确允许它(E.x sg-xxxxx ALL TCP)。这仅在您的 lambda 尝试通过私有 ip 访问数据库时才有效。
如果它试图通过 public IP 访问它,它将无法正常工作,您还需要为此打孔。
不过还有更好的方法:
- 为您的 lambda 创建单独的安全组
- 在 RDS sg 中允许端口
3306
上的入站流量用于 lambdas sg。
谢谢大家的帮助,结果和我想的不一样。代码中的 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');
});
};
问题不是超时,而是您关闭连接的方式。如果您不想等待回调或在 .end(function(err) { //Now call your callback });
中关闭连接时正确使用回调,请改用 .destroy()
有关更深入的解释,请参阅 this thread。
虽然使用上下文会起作用,但您只需将 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');
});
};
答案在文档中(我花了几个小时才找到这个):
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html
在 "Comparing the Context and Callback Methods" 部分中,它有一个 "Important" 注释来解释事情。
便条底部写着:
Therefore, if you want the same behavior as the context methods, you must set the context object property, callbackWaitsForEmptyEventLoop, to false.
基本上,回调会持续到事件循环结束,而不是结束事件循环的上下文。因此设置 callbackWaitsForEmptyEventLoop 使回调像上下文一样工作。
我也遇到过类似的超时情况。问题不是在 connection.connect()
之后执行 connection.end()
。 Connection.end()
应该在 callback
之前完成。
工作代码:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'host_name',
user : 'root',
password : 'password'
});
module.exports.handler = (event, context, callback) => {
// **Connection to database**
connection.connect(function(err) {
if (err) {
console.error('Database connection failed: ' + err.stack);
return;
}
console.log('Connected to database.');
});
// **Hit DB Query**
connection.query("Query", function(err, rows, fields) {
console.log(rows);
});
//**Close Connection**
connection.end(); ***// Missing this section will result in timeout***
//**Send API Response**
callback(null, {
statusCode: '200',
body: "Success",
headers: {
'Content-Type': 'application/json',
},
});
};
当您最初设置数据库时,它会自动创建一个安全组。默认为您设置数据库的 IP。当您从 lambda 运行 时,此规则会阻止流量。查看您的数据库错误日志,您可以确认它正在拒绝连接。
***** could not be resolved: Name or service not known
您需要在安全组中创建规则以允许 lambda 流量。转到您的 RDS 实例控制台并单击安全组 select 入站。在那里你会看到规则。然后打电话向世界开放,找到 AWS lambda IP 或创建 VPC。
connection.end() 应该在回调之后:
所以工作代码:
'use strict';
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'xxxxxx.amazonaws.com',
user : 'testuser',
password : 'testPWD',
port : 3306,
database: 'testDB',
debug : false
});
module.exports.handler = (event, context, callback) => {
// **Connection to database**
connection.connect(function(err) {
if (err) {
console.error('Database connection failed: ' + err.stack);
context.fail();
return;
}
else{
console.log('Connected to database.');
}
});
connection.query('show tables from testDB', function (error, results, fields) {
if (error) {
console.log("error: connection failed with db!");
connection.destroy();
throw error;
} else {
// connected!
console.log("info: connection ok with db!");
console.log(results);
context.succeed("done");
callback(error, results);
}
});
//Send API Response
callback(null, {
statusCode: '200',
body: 'succeed',
headers: {
'Content-Type': 'application/json',
},
});
//Close Connection
connection.end(); // Missing this section will result in timeout***
};
我花了大约 2 天的时间才弄清楚确切的问题。在我的例子中,RDS 和 Lambda 函数都在相同的 VPC、子网和安全组中,并添加了必需的角色,但仍然出现套接字超时异常。我能够通过遵循以下 link -
更改入站和出站规则来解决问题
https://aws.amazon.com/premiumsupport/knowledge-center/connect-lambda-to-an-rds-instance/
我正在尝试使用连接到我的 RDS 数据库的 Node.js 编写 Lambda 函数。数据库正在运行并且可以从我的 Elastic Beanstalk 环境中访问。当我 运行 函数时,它 returns 超时错误。
尝试将超时增加到 5 分钟,结果完全相同。
我经过一些研究得出的结论是,这可能是一个安全问题,但无法在亚马逊的文档或 this 答案中找到解决方案(这是我能找到的关于该主题的唯一答案) ).
以下是安全详细信息:
- 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');
});
};
我得到的结果是:
"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"
我正在分享我连接RDS的经验。
You need to enable
VPC
access for theLambda function
, during which you will assign it a Security Group.
然后,在分配给 RDS 实例的安全组中,您将为分配给 Lambda 函数的安全组启用访问权限。
您可以获得更多信息here
Both the RDS and the Lambda are in the same security group.
这是关键。默认不允许同一个安全组内的通信。并且您需要明确允许它(E.x sg-xxxxx ALL TCP)。这仅在您的 lambda 尝试通过私有 ip 访问数据库时才有效。
如果它试图通过 public IP 访问它,它将无法正常工作,您还需要为此打孔。
不过还有更好的方法:
- 为您的 lambda 创建单独的安全组
- 在 RDS sg 中允许端口
3306
上的入站流量用于 lambdas sg。
谢谢大家的帮助,结果和我想的不一样。代码中的 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');
});
};
问题不是超时,而是您关闭连接的方式。如果您不想等待回调或在 .end(function(err) { //Now call your callback });
.destroy()
有关更深入的解释,请参阅 this thread。
虽然使用上下文会起作用,但您只需将 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');
});
};
答案在文档中(我花了几个小时才找到这个): http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html
在 "Comparing the Context and Callback Methods" 部分中,它有一个 "Important" 注释来解释事情。
便条底部写着:
Therefore, if you want the same behavior as the context methods, you must set the context object property, callbackWaitsForEmptyEventLoop, to false.
基本上,回调会持续到事件循环结束,而不是结束事件循环的上下文。因此设置 callbackWaitsForEmptyEventLoop 使回调像上下文一样工作。
我也遇到过类似的超时情况。问题不是在 connection.connect()
之后执行 connection.end()
。 Connection.end()
应该在 callback
之前完成。
工作代码:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'host_name',
user : 'root',
password : 'password'
});
module.exports.handler = (event, context, callback) => {
// **Connection to database**
connection.connect(function(err) {
if (err) {
console.error('Database connection failed: ' + err.stack);
return;
}
console.log('Connected to database.');
});
// **Hit DB Query**
connection.query("Query", function(err, rows, fields) {
console.log(rows);
});
//**Close Connection**
connection.end(); ***// Missing this section will result in timeout***
//**Send API Response**
callback(null, {
statusCode: '200',
body: "Success",
headers: {
'Content-Type': 'application/json',
},
});
};
当您最初设置数据库时,它会自动创建一个安全组。默认为您设置数据库的 IP。当您从 lambda 运行 时,此规则会阻止流量。查看您的数据库错误日志,您可以确认它正在拒绝连接。
***** could not be resolved: Name or service not known
您需要在安全组中创建规则以允许 lambda 流量。转到您的 RDS 实例控制台并单击安全组 select 入站。在那里你会看到规则。然后打电话向世界开放,找到 AWS lambda IP 或创建 VPC。
connection.end() 应该在回调之后:
所以工作代码:
'use strict';
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'xxxxxx.amazonaws.com',
user : 'testuser',
password : 'testPWD',
port : 3306,
database: 'testDB',
debug : false
});
module.exports.handler = (event, context, callback) => {
// **Connection to database**
connection.connect(function(err) {
if (err) {
console.error('Database connection failed: ' + err.stack);
context.fail();
return;
}
else{
console.log('Connected to database.');
}
});
connection.query('show tables from testDB', function (error, results, fields) {
if (error) {
console.log("error: connection failed with db!");
connection.destroy();
throw error;
} else {
// connected!
console.log("info: connection ok with db!");
console.log(results);
context.succeed("done");
callback(error, results);
}
});
//Send API Response
callback(null, {
statusCode: '200',
body: 'succeed',
headers: {
'Content-Type': 'application/json',
},
});
//Close Connection
connection.end(); // Missing this section will result in timeout***
};
我花了大约 2 天的时间才弄清楚确切的问题。在我的例子中,RDS 和 Lambda 函数都在相同的 VPC、子网和安全组中,并添加了必需的角色,但仍然出现套接字超时异常。我能够通过遵循以下 link -
更改入站和出站规则来解决问题https://aws.amazon.com/premiumsupport/knowledge-center/connect-lambda-to-an-rds-instance/