2016-08-01 18 views
1

AWS Lambdaを使用して、SQLクエリを実行してRDS postgresデータベースからレコードを取得し、結果にSQSメッセージベースを作成する非常に単純なタスクを実行しました。pg-promiseを使用してAWS Lambdaの実行時間が長い理由

Amazonはデフォルトでノード4.3エンジンを使用しているaws-sdkモジュールしか提供していないため、この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を見れば、私のラムダ関数をテスト、機能自体は実行に周りの500msかかったが、それはそれは実際30502.48ミリ秒を要したことを述べている(参照:スクリーンショット:ここでは私が使用しているコードがあります)。

enter image description here enter image description here

だから私は私の318キロバイトパッケージを解凍し、それを実行を開始するために30秒を取っている推測していますか?私のためにはほんの冗談か何かが欠けている?私はzipをアップロードしようとしたが、私のパッケージをS3にアップロードして、それが速かったかどうかを確認したが、まだ同じレイテンシがある。私は本当にそれから離れて移動する必要はありませんので、私はPythonのバージョンがネイティブに任意のカスタムパッケージなしでSQL要求を実行できることに気づいた

が...

すべての私たちのアプリケーションはノードで書かれている、しかし、私が持っていますAmazonがデータベースとのやりとりのための基本的なnpmモジュールを提供していない理由を理解するのが難しい。

ご意見やご質問は歓迎します。この時点で私はLambdaが毎分トリガされるスクリプトを実行するのに30秒かかるなら、Lambdaが有益だろうと確信していません...

誰もが同じ問題に直面していますか?


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

私はログを最初に持っています(最初の行は "データベースに接続しています" )そして最後に(cf. cloudwatchのスクリーンショットを参照)、私は自分のコードの実行時間が〜500ミリ秒であることを知っているか分かっています。請求されている30秒間は説明しません。あなたが提供したドキュメントを読んでも、この30秒間に何が起こっているのかは説明していません。解凍するのは時間ですか?コンテナを作成するには? – maxwell2022

答えて

3

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

1つの形式または別の形式で接続プールを使用するライブラリが多数あります。これらは通常、構成可能な非活動期間の後に終了します。

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

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

これは、仕上げ直後に終了する必要があるので、code examplesのほとんどにも示されています。

関連する問題