st7*_*t78 46 node.js aws-lambda
我正在尝试在S3中处理上传的文件.由于getObject是异步主函数在处理完成之前结束,因此AWS在3-4秒内杀死lambda.
更糟糕的是,处理方法中还包含异步操作 - 它会进行http调用.
在高级别,我的代码看起来像:
exports.handler = function(event, context) {
// Get the object from the event and show its content type
var bucket = event.Records[0].s3.bucket.name;
var key = event.Records[0].s3.object.key;
var params = {
Bucket: bucket,
Key: key
};
s3.getObject(params, function(err, data) {
if (err) {
...
} else {
processFile(data.Body.toString(), 0);
console.log("ok");
}
});
//need to wait here till processFile is done
};
processFile = function(content, start) {
... build url to call
http.get(url, function(res) {
console.log("Got response: " + res.statusCode + ");
processFile(content, start + 1);
});
}
Run Code Online (Sandbox Code Playgroud)
我发现nodejs中存在异步但亚马逊不包含它; 两者都需要('async')或require('sleep)导致错误.
Lambda超时配置为60秒,但它在3-4秒内退出.
Neo*_*Neo 34
开发人员的生活在不断变化,我们现在在lambda上有NodeJS 8.对于现在看这个的人,请查看:
Lambda节点8.10与节点6.10的比较:https: //aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/
JS异步的基础知识:https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
更多aws sdk示例:https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html
有关wtf .promise()方法的详细信息位于第一个链接:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#promise-property
这是我对一个基本示例的看法(尝试粘贴到您自己的lambda中):
exports.handler = async (event) => {
function wait(){
return new Promise((resolve, reject) => {
setTimeout(() => resolve("hello"), 2000)
});
}
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
console.log(await wait());
return 'exiting'
};Run Code Online (Sandbox Code Playgroud)
以上产量:
你可以看到它等了12秒而没有杀死我的功能:)
每次等待TODO不止一件事,使用Promise.all([])语法如下:
exports.handler = async (event) => {
var uploadPromises = [];
folder.files.forEach(file => {
uploadPromises.push( s3.putObject({
Bucket: "mybucket",
Key: file.name,
Body: file.data
}).promise());
});
await Promise.all(uploadPromises);
return 'exiting'
};
Run Code Online (Sandbox Code Playgroud)
下面的Orignal答案
我的手上也有同样的问题.
问题是javascript事件循环是空的,所以Lambda认为它已经完成了.
这就是我解决这个问题的方法.我意识到这不是理想的,我希望有更好的方法,但我不想a)添加库,b)协调lambda调用,或c)切换到另一种语言.
在一天结束时,它的工作原理.
exports.handler = (event, context, callback) => {
var response;
var callBackCount;
/*
Ensures the javascript event loop is never empty.
This is the key to keeping lambda from exiting early
*/
setInterval(function(){}, 1000);
/*
Tell lambda to stop when I issue the callback.
This is super important or the lambda funciton will always go until it hits the timeout limit you set.
*/
context.callbackWaitsForEmptyEventLoop = false;
//My way of determining when I'm done with all calls
callBackCount = 0;
//My info to return
response = "";
//Various functions that make rest calls and wait for a response
asyncFunction1();
asyncFunction2();
asyncFunction3();
//Same for asyncFunction 2 and 3
function asyncFunction1(){
response += callBackResponseForThisMethod;
returnResponse();
}
function returnReponse(){
callBackCount++;
if(callBackCount == 3){
//Lambda will stop after this as long as context.callbackWaitsForEmptyEventLoop was set to false
callback(null, JSON.stringify(response));
}
}
};Run Code Online (Sandbox Code Playgroud)
http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
async不包括但这并不意味着你不能自己添加它.只需在本地添加包(npm install async),并node_modules在上传Lambda函数之前在ZIP中包含该文件夹.
如果你想单独处理dev依赖项(例如:test,aws-sdk在本地执行你的函数等),你可以devDependencies在你的下面添加它们package.json.此外,如果您想自动化开发,测试,部署和推广代码的过程,这两个回购将变得非常方便.
使用异步/等待
let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();
let data;
exports.handler = async (event) => {
try {
data = await lambda.getAccountSettings().promise();
}
catch (err) {
console.log(err);
return err;
}
return data;
};
Run Code Online (Sandbox Code Playgroud)
我认为你的lambda函数应该以context.done()调用结束.例如,尝试以这种方式添加它:
s3.getObject(params, function(err, data) {
if (err) {
...
context.done("Error: " + err.stack);
} else {
processFile(data.Body.toString(), 0);
console.log("ok");
context.done(null, "success");
}
});
Run Code Online (Sandbox Code Playgroud)
将Lambda想象成一个可以在一定时间内运行的程序.您进行异步调用的事实很好,因为(虚拟)处理器可能会交错这些调用.但是,如果Lambda程序的任何部分比分配的时间花费的时间更长,那么执行将失败.这是你做出的妥协,也是亚马逊赚钱的方式; 通过卖给你更多的时间或记忆.
要解决这个问题,您可以增加分配Lambda函数的内存.这不仅可以增加RAM,还可以提高虚拟处理器的速度.您可以做的另一件事是增加超时.AWS Lambda现在允许最多512 MB的RAM和最多5分钟的处理时间.截至这篇文章,这些数字可能已经改变,所以请查看最新的限制.要更改此设置,请转到您的功能,然后进行配置,最后进行高级操作.
如果您还想使用require('async');pack或require('sleep');pack,则需要将函数作为以下zip文件上传:
Zip 我在这个问题中也解释了该文件夹的所有内容:
适用于Alexa Javascript的AWS Lambda函数中的MQTT
关于同步处理,您可以require('async');正常使用,只是使用如下async.series功能:
async.series([
function(callback) {
// to do the function 1
callback();
},
function(callback) {
// to do the function 2
callback();
},
function(callback) {
// to do the function 3
callback();
}
], function(err) {
// to do the function if any error happens...
if (err) {
//...
}
//....
});
Run Code Online (Sandbox Code Playgroud)
这样,该lambda功能将同步工作。
希望对您有帮助。