web-dev-qa-db-ja.com

AWS Lambda RDS接続タイムアウト

Node.jsを使用してRDSデータベースに接続するLambda関数を作成しようとしています。データベースは動作しており、Elastic Beanstalk環境からアクセスできます。関数を実行すると、タイムアウトエラーが返されます。

まったく同じ結果で、タイムアウトを最大5分間まで増加させようとしました。

いくつかの研究の後に私が思いついた結論は、おそらくセキュリティの問題であるが、Amazonのドキュメントまたは this answer(このトピックで見つけることができる唯一のもの)で解決策を見つけることができなかったということです。

セキュリティの詳細は次のとおりです。

  • RDSとLambdaは両方とも同じセキュリティグループに属します。
  • RDSには、すべてのトラフィックの受信および送信ルールがあります。
  • Lambdaには、そのロールにAmazonVPCFullAccessポリシーがあります。

私のコードは:

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context, callback) => {

   var connection = mysql.createConnection({
        Host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) callback(null, 'error ' +err);
      else callback(null, 'Success');
    });

};

私が得ている結果は次のとおりです。

"errorMessage": "2017-03-05T05:57:46.851Z 9ae64c49-0168-11e7-b49a-a1e77ae6f56c Task timed out after 10.00 seconds"
17
Sir Codesalot

助けてくれたすべての人に感謝したい。問題は私が思っていたものとは異なることが判明した。コードのcallbackは、AmazonのOWN DEFAULT SAMPLEにあるにもかかわらず、何らかの理由で機能しません。

作業コードは次のようになります。

'use strict';
console.log("Loading getContacts function");

var AWS = require('aws-sdk');
var mysql = require('mysql');

exports.handler = (event, context) => {

   var connection = mysql.createConnection({
        Host     : '...',
        user     : '...',
        password : '...',
        port     : 3306,
        database: 'ebdb',
        debug    :  false
    });

    connection.connect(function(err) {
      if (err) context.fail();
      else context.succeed('Success');
    });

};
10
Sir Codesalot

コンテキストを使用しても機能しますが、追加する必要があるのはcontext.callbackWaitsForEmptyEventLoop = false;をハンドラに追加し、次のように通常どおりコールバックを使用します。

exports.handler = (event, context) => {
  context.callbackWaitsForEmptyEventLoop = false; 
  var connection = mysql.createConnection({
    //connection info
  });
  connection.connect(function(err) {
    if (err) callback(err); 
    else callback(null, 'Success');
  });
};

答えはドキュメントにあります(これを見つけるのに数時間かかりました): http://docs.aws.Amazon.com/lambda/latest/dg/nodejs-prog-model-using-old- runtime.html

「コンテキストメソッドとコールバックメソッドの比較」セクションには、事柄を説明する「重要な」メモがあります。

メモの下部には次のように記載されています。

したがって、コンテキストメソッドと同じ動作が必要な場合は、コンテキストオブジェクトプロパティcallbackWaitsForEmptyEventLoopをfalseに設定する必要があります。

基本的に、コールバックはイベントループを終了するコンテキストとは対照的に、イベントループの最後まで継続します。したがって、callbackWaitsForEmptyEventLoopを設定すると、コールバックがコンテキストのように機能します。

24
ambaum2

RDSとLambdaは両方とも同じセキュリティグループに属します。

それが鍵です。デフォルトでは、同じセキュリティグループ内の通信は許可されていません。また、明示的に許可する必要があります(E.x sg-xxxxx ALL TCP)。これは、ラムダがプライベートIPでdbにアクセスしようとした場合にのみ機能します。

パブリックIPでアクセスしようとすると、機能しないため、そのために必要な全体をパンチする必要があります。

しかし、より良いアプローチがあります:

  1. ラムダ用に個別のセキュリティグループを作成します
  2. ラムダsgのRDS sgのポート3306で受信トラフィックを許可します。
4
Vor

RDSを接続する際の経験を共有しています。

Lambda functionに対してVPCアクセスを有効にする必要があります。その間に、 セキュリティグループ を割り当てます。

次に、RDSインスタンスに割り当てられたセキュリティグループ内で、Lambda関数に割り当てられたセキュリティグループのアクセスを有効にします。

詳細情報を入手できます こちら

2
abdulbarik

最初にDBをセットアップすると、自動的にセキュリティグループが作成されます。 DBをセットアップしたIPがデフォルトになります。ラムダから実行すると、このルールはトラフィックをブロックします。 dbエラーログを確認すると、接続を拒否していることを確認できます。

***** could not be resolved: Name or service not known

ラムダトラフィックを許可するには、セキュリティグループにルールを作成する必要があります。 RDSインスタンスコンソールに移動し、セキュリティグループをクリックして、[受信]を選択します。そこにルールが表示されます。次に、世界に向けて電話をかけ、AWSラムダIPを見つけるか、VPCを作成します。

2
toonsend

connection.end()はコールバックの後でなければなりません:

動作するコード:

    'use strict';
var mysql = require('mysql');

var connection = mysql.createConnection({
    Host     : 'xxxxxx.amazonaws.com',
    user     : 'testuser',
    password : 'testPWD',
    port     : 3306,
    database: 'testDB',
    debug    : false        
});

module.exports.handler = (event, context, callback) => {
    // **Connection to database**      
    connection.connect(function(err) {
        if (err) {
            console.error('Database connection failed: ' + err.stack);
            context.fail();
            return;
        }
      else{ 
            console.log('Connected to database.');
        }
    });

    connection.query('show tables from testDB', function (error, results, fields) {
        if (error) {
            console.log("error: connection failed with db!");
            connection.destroy();
            throw error;
        } else {
            // connected!
            console.log("info: connection ok with db!");
            console.log(results);
            context.succeed("done");
            callback(error, results);
        }
    });

    //Send API Response
    callback(null, {
        statusCode: '200',
        body: 'succeed',
        headers: {
          'Content-Type': 'application/json',
        },
    });

    //Close Connection
    connection.end(); // Missing this section will result in timeout***

};
0
xiyulangzi

問題の原因はタイムアウトではなく、接続を閉じる方法です。 OR .destroy()で接続を閉じるときにコールバックを正しく使用するコールバックを待ちたくない場合は、代わりに.end(function(err) { //Now call your callback });を使用してください。

より詳細な説明については、 this thread を参照してください。

0
DR.

また、同様のタイムアウトシナリオに直面しました。問題はconnection.end()の後にconnection.connect()を実行していませんでした。 Connection.end()callbackの前に実行する必要があります。

作業コード:

  var mysql = require('mysql');

    var connection = mysql.createConnection({
        Host     : 'Host_name',
        user     : 'root',
        password : 'password'
    });


    module.exports.handler = (event, context, callback) => {

// **Connection to database**      
connection.connect(function(err) {
        if (err) {
          console.error('Database connection failed: ' + err.stack);
          return;
        }
        console.log('Connected to database.');
      });

    // **Hit DB Query**
      connection.query("Query", function(err, rows, fields) {
           console.log(rows);
        });


      //**Close Connection**

connection.end(); ***// Missing this section will result in timeout***

    //**Send API Response**
      callback(null, {
              statusCode: '200',
              body: "Success",
              headers: {
                  'Content-Type': 'application/json',
              },
      });

    };
0
user2735676