我开始使用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,该函数本身需要大约500毫秒才能运行,但它实际上却需要30502.48毫秒(请参见屏幕截图)。

node.js - 为什么使用pg-promise导致AWS Lambda执行时间长-LMLPHP
node.js - 为什么使用pg-promise导致AWS Lambda执行时间长-LMLPHP

因此,我猜测解压缩318KB软件包并开始执行需要30秒?对我来说这只是个玩笑,还是我错过了什么?我尝试上传zip并将包也上传到S3,以检查它是否更快,但是我仍然有相同的延迟。

我注意到Python版本可以在没有任何自定义包装的情况下本地执行SQ​​L请求...

我们所有的应用程序都是用node编写的,所以我真的不想离开它,但是我很难理解为什么Amazon不提供用于数据库交互的基本npm模块。

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

有人面临同样的问题吗?



更新:这是您不再需要连接时需要关闭的方式(再次感谢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

    [...]

最佳答案

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

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

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

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

在大多数code examples中也显示了它,因为那些需要在完成后立即退出。

关于node.js - 为什么使用pg-promise导致AWS Lambda执行时间长,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38690438/

10-16 23:20