我开始使用AWS Lambda执行一个非常简单的任务,即执行SQL查询以从RDS postgres数据库检索记录并根据结果创建SQS消息。
由于Amazon默认只提供aws-sdk
模块(使用节点4.3引擎),我们需要执行此SQL查询,因此我们必须创建一个包含pg-promise
的自定义部署包。这是我正在使用的代码:
console.info('Loading the modules...');
var aws = require('aws-sdk');
var sqs = new aws.SQS();
var config = {
db: {
username: '[DB_USERNAME]',
password: '[DB_PASSWORD]',
host: '[DB_HOST]',
port: '[DB_PORT]',
database: '[DB_NAME]'
}
};
var pgp = require('pg-promise')({});
var cn = `postgres://${config.db.username}:${config.db.password}@${config.db.host}:${config.db.port}/${config.db.database}`;
if (!db) {
console.info('Connecting to the database...');
var db = pgp(cn);
} else {
console.info('Re-use database connection...');
}
console.log('loading the lambda function...');
exports.handler = function(event, context, callback) {
var now = new Date();
console.log('Current time: ' + now.toISOString());
// Select auction that need to updated
var query = [
'SELECT *',
'FROM "users"',
'WHERE "users"."registrationDate"<=${now}',
'AND "users"."status"=1',
].join(' ');
console.info('Executing SQL query: ' + query);
db.many(query, { status: 2, now: now.toISOString() }).then(function(data) {
var ids = [];
data.forEach(function(auction) {
ids.push(auction.id);
});
if (ids.length == 0) {
callback(null, 'No user to update');
} else {
var sqsMessage = {
MessageBody: JSON.stringify({ action: 'USERS_UPDATE', data: ids}), /* required */
QueueUrl: '[SQS_USER_QUEUE]', /* required */
};
console.log('Sending SQS Message...', sqsMessage);
sqs.sendMessage(sqsMessage, function(err, sqsResponse) {
console.info('SQS message sent!');
if (err) {
callback(err);
} else {
callback(null, ids.length + ' users were affected. SQS Message created:' + sqsResponse.MessageId);
}
});
}
}).catch(function(error) {
callback(error);
});
};
在测试我的lambda函数时,如果你看一下WatchLogs,这个函数本身需要大约500ms来运行,但它说实际需要30502.48 ms(参见截图)。
所以我猜测解压缩318KB软件包并开始执行它需要30秒?那对我来说只是一个笑话,还是我错过了什么?我尝试上传zip并将我的软件包上传到S3以检查它是否更快但我仍有相同的延迟。
我注意到Python版本本身可以执行SQL请求而无需任何自定义打包...
我们所有的应用程序都是用节点编写的,所以我真的不想放弃它,但是我很难理解为什么亚马逊没有为数据库交互提供基本的npm模块。
欢迎任何评论或帮助。在这一点上,如果运行每分钟触发的脚本需要30秒钟,我不确定Lambda会对我们有益......
任何人都面临同样的问题?
更新:这就是您需要在不再需要时立即关闭连接的方式(再次感谢Vitaly的帮助):
exports.handler = function(event, context, callback) {
[...]
db.many(query, { status: 2, now: now.toISOString() }).then(function(data) {
pgp.end(); // <-- This is important to close the connection directly after the request
[...]
答案 0 :(得分:3)
执行时间应根据正在执行的操作的长度来衡量,而不是应用程序退出所需的时间。
有许多库以一种或另一种形式使用连接池。这些通常在可配置的不活动时段后终止。
如果pg-promise依次使用node-postgres,则此类不活动时间由参数poolIdleTimeout确定,默认为30秒。使用pg-promise,您可以通过pgp.pg.defaults.poolIdleTimeout
访问它。
如果希望在执行完最后一个查询后退出进程,则需要通过调用pgp.end()
来关闭连接池。有关详细信息,请参阅章节Library de-initialization。
大多数code examples也会显示,因为那些需要在完成后立即退出。