2017-05-21 10 views
0

私はここで間違っている世界を理解しようと壁に向かって頭を叩いています。私はNodeJS 6.10を使ってラムダ関数を書いています。この関数は、S3バケットの1つから複数のイメージを取得して処理することになっています。私は、JavaScriptの非同期性を取り入れている、あるいは、とにかくしようとしていて、これらが同時に起こるのを許して、それらのすべてが完了した後に何かを待ってやることを許可しています。私はコードをここでは最小限に抑えて書いていますが、私が見ている問題を再現しています。問題は、画像のどれも検索されていないことです。実際、ラムダ関数が実際にそれらを取得しようとしている兆候はなく、コールバックが一度も起動されないという兆候はありません。ここでS3JgetObjectを使用したLambdaのNodeJS

はコードです:

console.log('Executing testImg method.'); 
var aws = require('aws-sdk'); 
var s3 = new aws.S3(); 

var imgData = {}; 

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

    var imgs = ['img_1', 'img_2', 'img_3', 'img_4', 'img_5', 'img_6', 'img_7', 'img_8']; 
    var imgPromises = []; 
    console.log('Grabbing images: ' + imgs); 
    imgs.forEach(function(img) { 
     console.log(img); 
     var myPromise = s3.getObject({ 
      Bucket: 'photoBucket', 
      Key: 'images/' + img + '.png' 
     }).promise(); 
     imgPromises.push(myPromise); 
     myPromise.then(function(result) { 
      console.log('Got ' + img); 
      imgData[img] = result.Body; 
     }); 
    }); 
    Promise.all(imgPromises).then(function() { 
     console.log(imgData); 
     context.succeed(); 
    }); 

} 

そして、ここではラムダから出力されます:

START RequestId: <UUID> Version: $LATEST 
2017-05-21T18:53:31.187Z <UUID> Grabbing images: img_1,img_2,img_3,img_4,img_5,img_6,img_7,img_8 
2017-05-21T18:53:31.187Z <UUID> img_1 
2017-05-21T18:53:31.625Z <UUID> img_2 
2017-05-21T18:53:31.648Z <UUID> img_3 
2017-05-21T18:53:31.706Z <UUID> img_4 
2017-05-21T18:53:31.707Z <UUID> img_5 
2017-05-21T18:53:31.708Z <UUID> img_6 
2017-05-21T18:53:31.766Z <UUID> img_7 
2017-05-21T18:53:31.767Z <UUID> img_8 
END RequestId: <UUID> 
REPORT RequestId: <UUID> Duration: 10002.24 ms Billed Duration: 10000 ms Memory Size: 128 MB Max Memory Used: 80 MB 
2017-05-21T18:53:41.173Z <UUID> Task timed out after 10.00 seconds 

あなたは出力から見ることができるように、にconsole.log(IMG)のラインがどこに実行します画像の名前を印刷します。しかし、個々の.then()ブロック内のコードは実行されません(例えば、console.log( 'Got' + img))、最終的なPromise.allブロックのコードは実行されません、および関数呼び出しを終了させる機能を成功

また、私が試してみましたいくつか他のもの:。。。

  • 実行をローカル+ラムダローカルNodeJSを使用してコードそれが正常に動作します
  • ラン
  • Lambdaのコードを、明示的な資格情報を使用して実行するのではなく、Lambdaの役割を使用できるようにします。 AWSラムダではまだ失敗します。
  • ラムダでは1つのイメージを完全に正常にダウンロードできますが、ドキュメントではこれが悪いことを示すことはできませんが、好きではないと思われるgetObjectを何回か呼び出す方法です。
  • 私はループ内から個々のmyPromise.then()呼び出しを削除し、Promises.all()ブロック内のすべてを実行しようとしましたが、AWSで実際に実行されているコードにはなりません。

私はそれらをそれぞれ同期して実行することができますが、1)動的なやり方でこれを行うのは難しいです(事前に取得する必要があるファイルの数はわかりません) 、2)これはAsync JSが最近注目していることすべてに反するようだ。

ご意見をいただければ幸いです。

+1

あなたのコードは、成功したシナリオだけを処理しています。 '.catch()'または '.then()'に2番目の関数を追加する必要があります。エラーメッセージをすべて捕まえて印刷することを約束しています。正確に何が起こっているかを知る。また、NATゲートウェイなしでVPC内にLambda機能を配置しています(S3 API呼び出しがタイムアウトする可能性があります)。 –

+0

ありがとうございます。私はそれを解決策として掲示しておいて、それがあなたのために正しいと印を付けることができれば幸いです。私はある時点でcatch/errorコードをいくつか持っていましたが、接続するデフォルトのタイムアウトはラムダ関数の制限の大半よりも長いため、エラーチェックコードに到達することさえありませんでした。 プライベートデータベースサーバーにアクセスするためにラムダ関数をVPCに入れていましたが、外部のS3エンドポイントについても考えていませんでした。正しく配置されたNATゲートウェイといくつかの減少したHTTP接続タイムアウトがこれを解決しました。ありがとう! –

答えて

0

わかりましたので、S3は、公共のインターネットリソースにアクセスする必要についてのMark Bさんのコメントには、その場でだった、とここでは三つの可能なソリューションです:へのルートを持っているパブリックサブネットに

  • 移動ラムダ関数IGW経由のインターネット。インスタンスを公開する理由がないので、私はこのルートに行きたくはありませんでしたが、それはオプションです。
  • NATゲートウェイ(以前はNATインスタンス)を設定し、その方法でインターネットエンドポイントにトラフィックを送信できるようにルートテーブルを設定します。残念ながら、NATゲートウェイにはコストがかかり、毎月の請求書を発行したくありませんでした。
  • プライベートサブネット内のVPCにS3エンドポイントを追加し、プライベートサブネット内のアイテムがそのS3エンドポイントにアクセスできるようにルートテーブル、セキュリティグループ、およびポリシーを設定することでした。これは完全に機能します。

右向きのナッジのためにマークしていただきありがとうございます。