Функция AWS Lambda отключена, но работает на локальном экземпляре - PullRequest
0 голосов
/ 12 марта 2019

Я пишу приложение NodeJS на AWS, которое выполняет следующие действия:

  • читает XML с удаленного URL
  • анализирует данные и сохраняет их в формате 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(); 

}

1 Ответ

0 голосов
/ 12 марта 2019
  1. Полагаю, поскольку вы сказали, что эта программа работает нормально локально, вы неправильно настроили группу безопасности , связанную с Lambda . Убедитесь, что у вас есть все исходящие порты и правильные входящие порты открыты. Чтобы подтвердить, что это проблема, или, по крайней мере, получить более точную обратную связь, попробуйте добавить более подробную регистрацию к вашему запросу axios. Вот довольно подробный пример из axios docs ...


}).catch( (error) => {
    console.log(`[ERROR] axios: ${error}`);
    if (error.response) {
        // The request was made and the server responded with a status code
        // that falls out of the range of 2xx
        console.log('error.response.data'error.response.data);
        console.log('error.response.status',error.response.status);
        console.log('error.response.headers',error.response.headers);
    } else if (error.request) {
        // The request was made but no response was received
        // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
        // http.ClientRequest in node.js
        console.log('Error request:',error.request);
    } else {
        // Something happened in setting up the request that triggered an Error
        console.log('Error message', error.message);
    }
    console.log(error.config);
});

Вы должны получить сообщение об ошибке на объекте error.request, которое может помочь в дальнейшем устранении неполадок.

  1. Гораздо менее вероятно, что причина вашей проблемы, но стоит упомянуть, что .then() методы, которые вы связываете с s3Promise, будут выполняться асинхронно, поэтому s3Status[asset] = 1 не обязательно завершится, пока s3Ready(); не достигнет условного if (count === s3Assets.length) чтобы вы могли иметь здесь состояние гонки. Это маловероятно, но я все равно исправлю, потому что это может привести к ошибке в будущем. Запустите этот пример, чтобы понять, что я имею в виду ...


var test = ()=>new Promise(resolve=> resolve());

test()
  .then(()=> { setTimeout(()=>{console.log('one')},3000)})
  .then(()=>{console.log('two')})

Это назначение s3Status[asset] = 1 является синхронным, поэтому вы должны попытаться переместить s3Ready() в этот же .then() блок ...

s3Promise.then( (data) => {
    s3Status[asset] = 1;
    console.log('\n');
    console.log(`[SUCCESS] s3 Upload: ${data.Location}`);
    s3Ready();
}).catch( (error) => {
    console.log(`[ERROR] s3 Upload: ${error}`);
});
...