1

我开始使用 AWS Lambda 执行一个非常简单的任务,即执行 SQL 查询以从 RDS postgres 数据库中检索记录并根据结果创建 SQS 消息。

因为亚马逊默认只提供aws-sdk模块(使用 node 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 毫秒(参见屏幕截图)。

在此处输入图像描述 在此处输入图像描述

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

我注意到 Python 版本可以在没有任何自定义打包的情况下本机执行 SQL 请求...

我们所有的应用程序都是用 node 编写的,所以我真的不想离开它,但是我很难理解为什么亚马逊没有为数据库交互提供基本的 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

    [...]
4

1 回答 1

3

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

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

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

如果您希望您的进程在执行完最后一个查询后退出,您需要关闭连接池,方法是调用pgp.end(). 有关详细信息,请参阅库反初始化一章。

大多数代码示例中也显示了它,因为这些示例需要在完成后立即退出。

于 2016-08-01T12:13:13.977 回答