我有使用RDS的Lambda。我想改进它并使用Lambda连接缓存。据我所知,我已经找到了几篇文章,并在我这边实施了。但是现在,我不确定这是否是正确的方法。
我有Lambda(运行节点8),其中有几个文件与require一起使用。我将从主函数开始,直到到达MySQL初始化程序,这是确切的路径。一切都会超级简单,仅显示运行MySQL的代码流:
主要Lambda:
const jobLoader = require('./Helpers/JobLoader');
exports.handler = async (event, context) => {
const emarsysPayload = event.Records[0];
let validationSchema;
const body = jobLoader.loadJob('JobName');
...
return;
...//
职位代码:
const MySQLQueryBuilder = require('../Helpers/MySqlQueryBuilder');
exports.runJob = async (params) => {
const data = await MySQLQueryBuilder.getBasicUserData(userId);
MySQLBuilder:
const mySqlConnector = require('../Storage/MySqlConnector');
class MySqlQueryBuilder {
async getBasicUserData (id) {
let query = `
SELECT * from sometable WHERE id= ${id}
`;
return mySqlConnector.runQuery(query);
}
}
最后是连接器本身:
const mySqlConnector = require('promise-mysql');
const pool = mySqlConnector.createPool({
host: process.env.MY_SQL_HOST,
user: process.env.MY_SQL_USER,
password: process.env.MY_SQL_PASSWORD,
database: process.env.MY_SQL_DATABASE,
port: 3306
});
exports.runQuery = async query => {
const con = await pool.getConnection();
const result = con.query(query);
con.release();
return result;
};
我知道评估效果会显示实际结果,但是今天是星期五,直到下周下半年,我才能在Lambda上运行它。而且,实际上,周末开始真是太棒了,知道我朝着正确的方向……还是不正确。
感谢您的投入。
答案 0 :(得分:2)
第一件事是了解require
在NodeJS中的工作方式。如果您有兴趣了解更多有关此知识的信息,我建议您阅读此article。
现在,一旦您需要连接,便永久拥有它,并且不再需要它。这与您要查找的内容相匹配,因为您不想每次都通过创建新的连接来使数据库不堪重负。
但是,有一个问题...
Lambda冷启动
每当您第一次调用Lambda函数时,它都会旋转一个包含您的函数的容器,并使该容器保持活动状态大约5分钟。只要您一次发出1个请求,很有可能每次都会击中同一个容器(尽管不能保证)。但是,如果您同时有2个请求,该怎么办?然后,另一个容器将与先前已预热的容器并行旋转。您刚刚在数据库上创建了另一个连接,现在有2个容器。现在,如果您有3个并发请求,会发生什么?是!再增加一个容器,等于再增加一个数据库连接。
只要对Lambda函数有新请求,默认情况下,它们就会扩展以满足需求(您可以在控制台中对其进行配置,以将执行限制为任意数量的并发执行-遵守帐户限制)
仅通过在函数调用时要求您的代码,就无法安全地确保与数据库的连接数量固定。好在,这不是你的错。这就是Lambda函数的行为。
...另一种方法是
例如,在真正的缓存系统(例如ElasticCache)中缓存所需的数据。然后,您可以让某个运行特定时间的CloudWatch Event触发一个Lambda函数。然后,此函数将查询您的数据库并将结果存储在您的外部缓存中。这样,您可以确保一次只能由一个Lambda打开数据库连接,因为它将尊重CloudWatch Event,该事件每次触发仅运行一次。
编辑:OP在评论部分中发送了链接后,我决定添加一些其他信息,以澄清提到的文章想要说的话
“简单。您可以在我们的处理程序函数范围之外存储变量。这意味着您可以在处理程序函数之外创建数据库连接池,然后可以在以后每次对该函数的调用中共享该数据库连接池。这允许进行合并。再次,您可以查看我的GitHub以获取示例。”
这正是您在做什么。这有效!但是问题是,如果您同时拥有N个连接(Lambda请求)。如果未设置任何限制,则默认情况下最多可以同时启动1000个Lambda函数。现在,如果您在接下来的5分钟内同时发出另外1000个请求,则很可能不会打开任何新连接,因为在先前的调用中已经打开了这些新连接,并且这些容器仍然有效。
答案 1 :(得分:0)
通过 Thales Minussi 添加到上面的答案,但适用于 Python Lambda。我正在使用 PyMySQL 并创建一个连接池,我在获取数据的 Lambda 中的处理程序上方添加了连接代码。执行此操作后,在执行 Lambda 实例后,我没有获得任何添加到数据库中的新数据。我发现了与此问题相关的错误报告 here 和 here。
对我有用的 solution 是在 Lambda 中的 SELECT 查询执行之后添加一个 conn.commit()
。
根据 PyMySQL documentation,conn.commit()
应该提交任何更改,但 SELECT
不会对数据库进行更改。所以我不确定为什么会这样。