Подтвердить что ты не робот

Как ждать асинхронных действий внутри AWS Lambda?

Я пытаюсь обработать загруженный файл в S3. Поскольку getObject заканчивается как основная задача, заканчивается до завершения обработки, а AWS убивает лямбда за 3-4 секунды.

Хуже того, метод обработки также имеет асинхронные операции в нем - он делает 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);
  });
}

Я узнаю, что в nodejs существует async, но он не включен amazon; Оба требуют ( "async" ) или требуют ( "сон" ) вызывает ошибки.

Время ожидания Lambda настроено на 60 секунд, но оно выйдет через 3-4 секунды.

4b9b3361

Ответ 1

async не входит, но это не значит, что вы не можете добавить его самостоятельно. Просто добавьте пакет локально (npm install async) и включите папку node_modules в свой ZIP перед загрузкой функции лямбда.

Если вы хотите обрабатывать зависимости dev отдельно (например: test, aws-sdk для выполнения вашей функции локально и т.д.), вы можете добавить их под devDependencies в свой package.json. Кроме того, если вы хотите автоматизировать процесс разработки, тестирования, развертывания и продвижения своего кода, эти два репозитория окажутся очень удобными.

Процедура Grunt для тестирования, упаковки и развертывания ваших lambdas

Инструмент командной строки для запуска и развертывания ваших лямбда-функций

Ответ 2

У меня была такая же проблема на моих руках.

Проблема в том, что цикл событий javascript пуст, поэтому Lambda думает, что это сделано.

Вот как я решил эту проблему. Я понимаю, что это не идеально, и я хочу, чтобы был лучший способ, но я не хотел: a) добавлять библиотеки, b) координировать лямбда-вызовы или 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));
            }
        }

    };

Ответ 3

Я думаю, что ваша лямбда-функция должна завершиться вызовом 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");
    }
});

Ответ 4

Подумайте о Lambda просто как программу, которую вы можете запустить за определенное время. Тот факт, что вы выполняете асинхронные вызовы, хорош, поскольку (виртуальный) процессор может чередовать эти вызовы. Однако, если какая-либо часть вашей Lambda-программы занимает больше времени, чем время, выделенное, ну, выполнение не будет выполнено. Это компромисс, который вы делаете и как Amazon зарабатывает деньги; продавая вам больше времени или памяти.

Чтобы исправить это, вы можете увеличить память, которую выделяет функция лямбда. Это не только увеличивает оперативную память, но и скорость вашего виртуального процессора. Еще одна вещь, которую вы можете сделать, - увеличить тайм-аут. AWS Lambda теперь позволяет вам до 512 МБ оперативной памяти и до 5 минут обработки. На этом посту эти цифры, возможно, изменились, поэтому отметьте здесь для последних ограничений. Чтобы изменить этот параметр, перейдите к своей функции, затем конфигурации и, наконец, расширенной.

Ответ 5

Если вы хотите использовать пакет require('async'); pack или require('sleep');, вам необходимо загрузить свою функцию в виде файла zip, например:

Создание пакета развертывания (Node.js)

zip все содержимое папки, как я объясню в этом вопросе:

MQTT в функции AWS Lambda для Alexa Javascript

Об синхронной обработке вы можете использовать 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) {
        //...
    }
    //....
});

Таким образом, функция lambda будет работать синхронно.

Я надеюсь помочь вам.

Ответ 6

Вместо этого вы можете сделать вызов synchronous; так как вы, кажется, обрабатываете свой файл в той же лямбда-функции.

Если по какой-либо причине вы хотите получить обратный вызов; вы можете сделать это путем прямого вызова лямбда или с помощью чего-то, что приведет к событию лямбда. Обратите внимание, что лямбда-функции предполагаются апатридами; поэтому вы должны передать всю необходимую информацию.