首页 > 解决方案 > Lambda 函数完成,但对 RDS 的查询不完整

问题描述

我试图使用 handler.async 对数据库(RDS)进行后查询。但是,我遇到了以下问题。

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

日志也会显示错误:

信息错误:致命错误后无法将查询排入队列。

以下是我的代码:

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  

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

标签: node.jsamazon-web-servicesaws-lambdaamazon-rds

解决方案


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

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

阅读如何:管理来自 AWS Lambda 无服务器函数的 RDS 连接

另请注意带有 AWS Lambda 的新Amazon RDS 代理

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


推荐阅读