Lambda上的NodeJS使用S3.getObject

时间:2017-05-21 19:22:59

标签: javascript node.js amazon-s3 aws-lambda

所以,我正在撞墙,试图找出世界上我在这里做错了什么。我正在使用NodeJS 6.10编写Lambda函数。该函数应该从我的一个S3存储桶中检索多个图像并进行处理。我正在接受JavaScript的异步特性,或者尝试,无论如何,并允许它们同时发生,然后在所有这些完成之后等待并做一些事情。我已将这里的代码提炼到我能写的最低限度,并且仍能重现我所看到的问题。问题是没有任何图像被检索 - 事实上,没有迹象表明Lambda函数实际上试图检索它们,并且没有迹象表明回调被触发。

以下是代码:

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();
    });

}

以下是Lambda的输出:

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块中的所有代码都没有运行(打印出整个数组) ,并调用success函数来终止函数。

另外,我尝试过其他一些事情:

  • 使用NodeJS + lambda-local在本地运行代码。它工作正常。
  • 在没有lambda-local的NodeJS中运行类似的代码。它工作正常。
  • 使用显式凭据在Lambda上运行代码,而不是允许它使用Lambda角色。它仍然在AWS Lambda上失败。
  • 下载单个图像在Lambda中运行得非常好 - 这是关于多次调用getObject的东西,它似乎不喜欢,但我在文档中找不到任何迹象表明这是一件坏事。
  • 我尝试从循环内部删除单个myPromise.then()调用,并在Promises.all()块中执行所有操作,并且再次,这不会导致代码实际在AWS中运行。

我可以把它们连在一起,这样它们每个都可以同步发生,但是1)很难以动态的方式做到这一点(不知道我需要提前获得的文件数量),以及2这似乎违背了Async JS目前所做的一切。

任何提示都将不胜感激。

1 个答案:

答案 0 :(得分:0)

好的,所以,Mark B关于S3需要访问公共互联网资源的评论是现场,以下是三种可能的解决方案:

  • 将Lambda函数移动到具有通过IGW到Internet的路由的公有子网。我真的不想走这条路,因为没有理由公开这些实例,但这是一个选择。
  • 配置NAT网关(以前称为NAT实例)并配置路由表以允许通过该方法流量到Internet端点。不幸的是,NAT网关会产生费用,我不想每月支付费用。
  • 我最终选择的是在我的私有子网内向我的VPC添加S3端点,然后配置路由表,安全组和策略,以便私有子网内的项可以访问该S3端点。这非常有效。

再次感谢马克,为了正确方向的推动。