【发布时间】:2019-03-12 18:43:41
【问题描述】:
我正在 AWS 上编写一个 NodeJS 应用程序,它执行以下操作:
- 从远程 URL 读取 XML
- 解析数据并将其作为 JSON 存储在 DynamoDB 上
- 上传 8 张图片到 s3 存储桶
代码在我的本地节点实例上运行良好。整个过程通常需要不到 3 秒的时间来完成。我可以通过检查 AWS s3 存储桶和 DynamoDB 来确认这一点。
但是,当我将其打包为由 Lambda 运行时,即使超时设置为 5 分钟并最大化内存,操作也会过期。检查日志时,我注意到 axios 的承诺在 Lambda 上运行时从未返回。有人能发现我的代码有什么问题吗?谢谢。
仅供参考,我是 Lambda 开发的新手。我将代码部署到 Lambda 的方式是将封闭的 export.handler 方法添加到我的本地代码中,并将其与模块和 package.json 一起压缩。我当然可以使用一些指导来简化这个过程。我提到这一点是因为我不确定这是否与问题有关。
谢谢。
exports.handler = function(event, context, callback) {
async function main() {
await getData();
updateDB();
updateAssets();
}
let dataStore = {};
let s3Assets = [
'photo1',
'photo2',
'photo3',
'photo4',
'photo5',
'logoLarge',
'logoSmall',
'logoCompany'
];
let s3Status = {};
s3Assets.map( (i) => {
// Initialize the status of all assets with 0 (false)
s3Status[i] = 0;
})
let s3Ready = () => {
let count = 0;
s3Assets.map( (i) => {
count += s3Status[i];
})
console.log(s3Status);
console.log(`Upload Count: ${count}`);
if (count === s3Assets.length) {
console.log(`[SUCCESS] All assets are updated`);
console.log('< END: updateAssets');
}
}
let getData = () => {
... // code omitted
}
let handleAsset = (asset) => {
let src = dataStore[asset];
let destination = dataStore.prefix + asset + '.jpg';
axios({
method:'get',
url: src,
responseType:'stream'
}).then( (response) => {
let body = response.data.pipe(zlib.createGzip());
let fileType = 'multipart/form-data';
let s3Promise = s3.upload({
Bucket: 'someBucket',
Key: destination,
Body: body,
ContentType: fileType,
ContentEncoding: 'gzip'
}).promise();
s3Promise.then( (data) => {
s3Status[asset] = 1;
console.log('\n');
console.log(`[SUCCESS] s3 Upload: ${data.Location}`);
}).then( () => {
s3Ready();
}).catch( (error) => {
console.log(`[ERROR] s3 Upload: ${error}`);
});
}).catch( (error) => {
console.log(`[ERROR] axios: ${error}`);
});
}
let updateAssets = () => {
console.log('> START: updateAssets');
s3Assets.map( (i) => {
handleAsset(i)
});
}
let updateDB = () => {
... // code omitted
}
main();
}
【问题讨论】:
-
我在我的 handleAssets 函数中的 axios 请求配置中添加了超时选项。正如预期的那样,axios 正在超时。
-
混合 Promise 链和 async/await 会使调试变得有点困难。我建议重构 Promise 链以使用 async/await 和 try/catch。但是我看到的主要问题是您从不表示成功或失败。你永远不会调用
callback或返回响应对象 -
您是如何配置 Lambda 函数的?是否配置为连接到 VPC 和子网?你能测试它是否有互联网连接(例如尝试从某个地方检索网页)吗?
-
@JohnRotenstein 谢谢。我没有使用 VPC。该函数能够更新 DynamoDB,所以我认为问题与处理 S3 上传的部分有关。
-
@bwest。谢谢。为了更清晰,我将在我的承诺链中添加返回值。
标签: node.js amazon-web-services aws-lambda axios