node.js - 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
请您提供建议并告诉我执行它的最佳方法是什么?
解决方案
在任何环境中管理 RDBMS 连接都不是一件容易的事。Lambda 在这里增加了一层复杂性。您需要了解热重启和冷重启之间的区别,它对在处理程序函数之外创建的资源意味着什么,连接池何时合适,以及何时以及如何释放连接。
与数据库的持久连接并不是特别适合微服务、FaaS 环境(如 Lambda)。这就是 Aurora Serverless 支持HTTP 数据 API的原因之一(希望其他数据库引擎在某个时候也能支持)。
阅读如何:管理来自 AWS Lambda 无服务器函数的 RDS 连接。
另请注意带有 AWS Lambda 的新Amazon RDS 代理。
query
在您的特定情况下,最明显的问题是您重复创建数据库连接但从未释放它们(除非这是我不知道的 mysql 包函数的内置功能)。
推荐阅读
- list - 如何创建一个包含 n 个过程应用程序的列表
- javascript - 从数组中提取最后 n 个元素而不干扰原始数组
- javascript - 更改 Redux 中的存储
- java - Android中是否有任何有效的方法来缩小文件中的大图像并将其保存到新文件而不会出现OOM异常
- java - 如何与批处理进行通信?
- spark-java - Spark 可以支持每条路由多少个并发请求?
- php - Symfony 中的简单查询返回 null
- header - Zip 是否使用字典进行压缩?是否可以提取该字典并将其转储到文本文件中?
- youtube-api - Youtube API - 允许订阅用户,但次日取走
- java - 在我的 txt 文件的每一行添加一个空格