2016-08-01 55 views
1

我开始使用AWS Lambda执行一个非常简单的任务,该任务正在执行SQL查询以从RDS postgres数据库检索记录并在结果上创建SQS消息库。为什么AWS Lambda执行时间很长使用pg-promise

由于默认情况下亚马逊仅提供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毫秒(见截图)。

enter image description here enter image description here

所以我猜它采取30秒,我的解压包318KB,并开始执行呢?这对我来说只是一个笑话,或者我错过了什么?我试图上传zip文件,并将我的软件包上传到S3,以检查它是否更快,但我仍然有相同的延迟。

我注意到,Python版本可本地没有任何定制包装执行SQL请求......

我们所有的应用程序都是用节点,所以我真的不想要移动远离它,但我有一个很难理解为什么亚马逊没有为数据库交互提供基本的npm模块。

欢迎任何评论或帮助。在这一点上,我不确定Lambda对我们是否有益,如果需要30秒来运行每分钟触发的脚本...

任何人都面临同样的问题?


UPDATE:这就是你需要(再次感谢维塔利他的帮助),只要你不需要它关闭连接了:

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

尝试添加更多日志记录以查明30秒来自哪里,无论是查询本身还是以后做的事情。您发布的信息中没有足够的信息来查明。AWS倾向于为支持该语言的“标准”的每种语言(以及AWS SDK)创建运行时环境。 Python可能会考虑SQL标准,而JavaScript不会。 –

+0

可能与设置期望有关:https://docs.aws.amazon.com/lambda/latest/dg/lambda-introduction-function.html#topic3 –

+0

我在开头有日志(第一行“连接到数据库” )和最后(比较cloudwatch截图),所以我知道我的代码的执行时间是500毫秒左右。它没有解释30个其他秒的结算。同时阅读您提供的文档,并不能解释在这30秒内发生了什么。是时候解压缩了吗?创建容器? – maxwell2022

回答

3

的执行时间应该根据正在执行的操作的长度来衡量,而不是应用程序退出需要多长时间。

有许多库在那里使用一种或另一种形式的连接池。这些通常在可配置的不活动时间段后终止。

pg-promise情况下,又使用node-postgres,不活动的期间由参数poolIdleTimeout,默认为30秒来确定。通过pg-promise,您可以通过pgp.pg.defaults.poolIdleTimeout访问它。

如果您希望在最后一次查询执行后退出进程,则需要通过调用pgp.end()来关闭连接池。有关详细信息,请参见章节Library de-initialization

它也显示在code examples的大部分,因为那些需要完成后退出。

相关问题