1

AWS Lambda を使用して、SQL クエリを実行して RDS postgres データベースからレコードを取得し、結果に基づいて SQS メッセージ ベースを作成するという非常に単純なタスクを実行し始めました。

aws-sdkデフォルトでは、Amazon はモジュール (ノード 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);
  });

};

ラムダ関数をテストするとき、WatchLogs を見ると、関数自体の実行には約 500 ミリ秒かかりましたが、実際には 30502.48 ミリ秒かかったことが示されています (スクリーンショットを参照)。

ここに画像の説明を入力 ここに画像の説明を入力

318KB のパッケージを解凍して実行を開始するのに 30 秒かかると思いますか? それは私にとって単なる冗談ですか、それとも何か足りないのですか? zip をアップロードし、パッケージを S3 にアップロードして高速かどうかを確認しようとしましたが、それでもレイテンシーは同じです。

Python バージョンは、カスタム パッケージなしでネイティブに SQL リクエストを実行できることに気付きました...

私たちのアプリケーションはすべて node で書かれているので、そこから離れたくはありませんが、なぜ Amazon がデータベースの相互作用のための基本的な 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

実行時間は、アプリケーションが終了するのにかかる時間ではなく、実行される操作の長さに基づいて測定する必要があります。

何らかの形で接続プールを利用するライブラリは数多くあります。これらは通常、構成可能な非アクティブ期間の後に終了します。

node-postgresを使用するpg-promiseの場合、そのような非アクティブ期間はパラメーターpoolIdleTimeoutによって決定され、デフォルトは 30 秒です。pg-promiseを使用すると、 経由でアクセスできます。pgp.pg.defaults.poolIdleTimeout

最後のクエリが実行された後にプロセスを終了させたい場合は、 を呼び出して接続プールをシャットダウンする必要がありますpgp.end()詳細については、ライブラリの初期化解除の章を参照してください。

また、終了直後に終了する必要があるため、ほとんどのコード例にも示されています。

于 2016-08-01T12:13:13.977 に答える