AWS Lambda 函数生命周期
AWS Lambda Function lifetime
考虑以下 AWS Lambda 函数:
var i = 0;
exports.handler = function (event, context) {
context.succeed(++i);
};
多次执行这个函数,我最终得到类似如下的输出:
> 0
> 1
> 2
> 0
> 1
> 0
> 3
> 2
> 4
> 1
> 2
如您所见,脚本似乎有 3 个单例,我在执行函数时随机出现在其中一个中。
这是预期的行为吗?我在文档中找不到任何相关信息。
我问这个是因为我打算连接到 MySQL 并保留一个连接池:
var MySQL = require('mysql');
var connectionPool = MySQL.createPool({
connectionLimit: 10,
host: '*****',
user: '*****',
pass: '*****',
database: '*****'
});
function logError (err, callback) {
console.error(err);
callback('Unable to perform operation');
}
exports.handler = function (event, context) {
connectionPool.getConnection(function (err, connection) {
err && logError(err, context.fail);
connection.query('CALL someSP(?)', [event.user_id], function (err, data) {
err && logError(err, context.fail);
context.succeed(data[0]);
connection.release();
});
});
};
需要使用connectionPool.end()
释放连接池,但是我应该在哪里执行呢?
如果我把它加在脚本的末尾(处理程序之后),那么连接池将在 lambda 函数第一次执行时立即关闭。
如果我在处理程序中处理连接池,那么连接池将关闭以供将来的请求使用。
此外,我应该处理它吗?如果我不处理它,连接将保留在池和内存中,但正如您在第一个代码示例中看到的那样,AWS 保留了我模块的 ~ 3 个单例,这意味着我最终会得到3 个不同的连接池,每个有 10 个连接。
除非我严重误解了你的问题,否则这是 lambda 的有据可查的预期行为。看这里:https://aws.amazon.com/lambda/faqs/
Lambda 启动您的容器实例以匹配您的 lambda 函数的使用模式。如果它现在没有被使用,那么它会将其旋转下来,如果它被大量使用,那么将创建更多的容器。您永远不应该依赖 lambda 函数中的持久状态。如果它是为了你的功能的生命周期,或者你正在优化某些东西,那么使用状态是可以的。
据我所知,您无法在任何给定时间控制内存中函数实例的数量,因此如果您担心用完 mysql 个连接,您应该相应地进行设计。
来自文档:
"AWS Lambda can start as many copies of your function as needed without lengthy deployment and configuration delays. There are no fundamental limits to scaling a function. AWS Lambda will dynamically allocate capacity to match the rate of incoming events."
直接适用于您的 mysql 问题,我总是 return 在您使用完池后连接到池。然后我会计算您希望有多少并发请求,并根据您的 mysql 服务器配置进行相应的计划。
考虑以下 AWS Lambda 函数:
var i = 0;
exports.handler = function (event, context) {
context.succeed(++i);
};
多次执行这个函数,我最终得到类似如下的输出:
> 0
> 1
> 2
> 0
> 1
> 0
> 3
> 2
> 4
> 1
> 2
如您所见,脚本似乎有 3 个单例,我在执行函数时随机出现在其中一个中。
这是预期的行为吗?我在文档中找不到任何相关信息。
我问这个是因为我打算连接到 MySQL 并保留一个连接池:
var MySQL = require('mysql');
var connectionPool = MySQL.createPool({
connectionLimit: 10,
host: '*****',
user: '*****',
pass: '*****',
database: '*****'
});
function logError (err, callback) {
console.error(err);
callback('Unable to perform operation');
}
exports.handler = function (event, context) {
connectionPool.getConnection(function (err, connection) {
err && logError(err, context.fail);
connection.query('CALL someSP(?)', [event.user_id], function (err, data) {
err && logError(err, context.fail);
context.succeed(data[0]);
connection.release();
});
});
};
需要使用connectionPool.end()
释放连接池,但是我应该在哪里执行呢?
如果我把它加在脚本的末尾(处理程序之后),那么连接池将在 lambda 函数第一次执行时立即关闭。
如果我在处理程序中处理连接池,那么连接池将关闭以供将来的请求使用。
此外,我应该处理它吗?如果我不处理它,连接将保留在池和内存中,但正如您在第一个代码示例中看到的那样,AWS 保留了我模块的 ~ 3 个单例,这意味着我最终会得到3 个不同的连接池,每个有 10 个连接。
除非我严重误解了你的问题,否则这是 lambda 的有据可查的预期行为。看这里:https://aws.amazon.com/lambda/faqs/
Lambda 启动您的容器实例以匹配您的 lambda 函数的使用模式。如果它现在没有被使用,那么它会将其旋转下来,如果它被大量使用,那么将创建更多的容器。您永远不应该依赖 lambda 函数中的持久状态。如果它是为了你的功能的生命周期,或者你正在优化某些东西,那么使用状态是可以的。
据我所知,您无法在任何给定时间控制内存中函数实例的数量,因此如果您担心用完 mysql 个连接,您应该相应地进行设计。
来自文档:
"AWS Lambda can start as many copies of your function as needed without lengthy deployment and configuration delays. There are no fundamental limits to scaling a function. AWS Lambda will dynamically allocate capacity to match the rate of incoming events."
直接适用于您的 mysql 问题,我总是 return 在您使用完池后连接到池。然后我会计算您希望有多少并发请求,并根据您的 mysql 服务器配置进行相应的计划。