Lambda 函数已完成,但对 RDS 的查询不完整



我试图使用handler.async对db(RDS(进行post查询。 但是,我遇到了以下问题。

一半的时间,lambda 函数完成,但查询未成功发送到 RDS。另一半时间,它将完全发送到lambda。尝试添加 setTimeout 函数以将 lambda 执行时间增加 3 秒,查询将一直发送。

日志还将显示错误:

INFO 错误:致命错误后无法将查询排队。

以下是我的代码:

var mysql = require('mysql');
var connection = mysql.createConnection({
host     : '***',
user     : '***',
password : '***',
database : '***'
});
exports.handler = async (event) => {
const sql = `INSERT INTO forms VALUES(777,2,3,4,5,6,7,8,9,10,11);`;
const query = (x) => {
return new Promise ((resolve,reject)=>{
resolve(connection.query(x, function (error, results, fields) {
console.log(error)
console.log(results)
console.log(fields)

}))})}
await query(sql)
}

使用超时功能,

var mysql = require('mysql');
var connection = mysql.createConnection({
host     : '***',
user     : '***',
password : '***',
database : '***'
});
exports.handler = async (event) => {
const sql = `INSERT INTO forms VALUES(777,2,3,4,5,6,7,8,9,10,11);`;
const query = (x) => {
return new Promise ((resolve,reject)=>{
resolve(connection.query(x, function (error, results, fields) {
console.log(error)
console.log(results)
console.log(fields)

}))})}
await query(sql)
await wait(3000)
}
const wait = (x) => {
return new Promise ((resolve,reject)=>{
setTimeout(()=>{resolve(console.log("delay"))}, x);
})
}

第一个值是主键。发送常量 777 进行检查,如果错误显示主键重复,则表示查询发送成功。如果没有错误,则表示尽管 lambda 已完成,但查询发送失败。

execution result succeeded but shows:
START RequestId: e541fe4b-6927-4fbb-90b4-750f77e5f460 Version: $LATEST
2019-12-19T01:54:45.212Z    e541fe4b-6927-4fbb-90b4-750f77e5f460    INFO    Error: **Cannot enqueue Query after fatal error**.
at Protocol._validateEnqueue (/var/task/node_modules/mysql/lib/protocol/Protocol.js:212:16)
at Protocol._enqueue (/var/task/node_modules/mysql/lib/protocol/Protocol.js:138:13)
at Connection.query (/var/task/node_modules/mysql/lib/Connection.js:201:25)
at /var/task/index.js:14:24
at new Promise (<anonymous>)
at query (/var/task/index.js:13:10)
at Runtime.exports.handler (/var/task/index.js:20:7)
at Runtime.handleOnce (/var/runtime/Runtime.js:66:25) {
code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
fatal: false
}2019-12-19T01:54:45.213Z   e541fe4b-6927-4fbb-90b4-750f77e5f460    INFO    undefined2019-12-19T01:54:45.213Z   e541fe4b-6927-4fbb-90b4-750f77e5f460    INFO    undefined2019-12-19T01:54:45.262Z   e541fe4b-6927-4fbb-90b4-750f77e5f460    INFO    delayEND RequestId: e541fe4b-6927-4fbb-90b4-750f77e5f460
REPORT RequestId: e541fe4b-6927-4fbb-90b4-750f77e5f460  Duration: 51.09 ms  Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 80 MB  

请您提供建议并告诉我哪种是执行它的最佳方法?

在任何环境中管理 RDBMS 连接都不是一件容易的事。Lambda 在这里增加了一层复杂性。您需要了解热重启和冷重启之间的区别、它对在处理程序函数之外创建的资源意味着什么、何时适合连接池,以及何时以及如何释放连接。

与数据库的持久连接不是特别适合像 Lambda 这样的微服务 FaaS 环境。这就是 Aurora Serverless 支持 HTTP Data API 的原因之一(希望其他数据库引擎在某个时候也会支持(。

阅读如何:从 AWS Lambda 无服务器函数管理 RDS 连接。

另请注意新的 Amazon RDS Proxy with AWS Lambda。

在您的特定情况下,最明显的问题是您反复创建数据库连接但从未释放它们(除非这是我不知道的 mysql 包query函数的内置功能(。

您可以将 lambda 超时增加到最多 15 分钟。但是,如果您通过 api 网关调用 lambda,则超时为 29 秒。

这是为我工作的代码。

const mysql = require('mysql');
const con = mysql.createConnection({
host: process.env.RDS_HOSTNAME,
user: process.env.RDS_USERNAME,
password: process.env.RDS_PASSWORD,
port: process.env.RDS_PORT,
connectionLimit: 10,
multipleStatements: true,// Prevent nested sql statements
debug: true
// ,database:'testdb1'
});

exports.handler = async (event) => {
try {
const data = await new Promise((resolve, reject) => {
con.connect(function (err) {
if (err) {
reject(err);
}
const sql = `INSERT INTO forms VALUES(777,2,3,4,5,6,7,8,9,10,11);`;
con.query(sql, function (err, result) {
if (err) {
console.log("Error->" + err);
reject(err);
}
resolve(result);
});
})
});
return {
statusCode: 200,
body: JSON.stringify(data)
}
} catch (err) {
return {
statusCode: 400,
body: err.message
}
}
};

参考:带有 RDS MySQL DDL 命令的 AWS lambda 不起作用

最新更新