Lambda @ Edge дает 502 только для некоторых изображений - PullRequest
2 голосов
/ 08 марта 2019

То, что мы делаем, это принимаем запрос на изображение типа «media / catalog / product / 3/0/30123 / 768x / lorem.jpg», затем мы используем исходное изображение, расположенное в «media / catalog / product / 3». /0/30123.jpg ", измените его размер до 768px и webp, если браузер поддерживает это, а затем верните новое изображение (если оно еще не кэшировано).

Если вы запросите: wysiwyg / lorem.jpg, он попытается создать веб-страницу с максимальным разрешением 1920 пикселей (без увеличения).

Кажется, это прекрасно работает до изображения шириной <= 1420 пикселей. Однако выше этого мы получаем только <code>HTTP 502: The Lambda function returned invalid json: The json output is not parsable.

Существует аналогичная проблема с SO, связанная с GZIP, однако, насколько я понимаю, на самом деле изображения GZIP не следует: https://webmasters.stackexchange.com/questions/8382/gzipped-images-is-it-worth/57590#57590

Но возможно, что исходное изображение уже загружено в S3 GZIPPED. Но gzip может быть ошибочным, потому что тогда он будет работать для небольших изображений? У нас отключен GZIP в Cloudfront.

Я дал функции Lamda @ Edge Resize максимальные ресурсы 3 ГБ памяти и время ожидания 30 секунд. Этого недостаточно для больших изображений?

Я удалил уже сгенерированные изображения, аннулировал Cloudfront, но он по-прежнему ведет себя так же ..

РЕДАКТИРОВАТЬ: ОБНОВЛЕНИЕ :

Я просто попробовал другое изображение, и затем оно отлично работает .. Я не представляю, почему и как я должен тогда решить сломанное изображение ... Я предполагаю, что Cloudfront кешировал 502 сейчас ... Я аннулировал, используя просто "* "но это не помогло .. Оба исходных файла - jpg.

Исходный исходный образ для рабочего - 6,1 МБ, а для нерабочего - 6,7 МБ, если это имеет значение.

У них есть эти ограничения: https://docs.aws.amazon.com/lambda/latest/dg/limits.html

Размер файла response.body составляет около 512 МБ, когда он перестает работать.

Ответы [ 2 ]

1 голос
/ 20 марта 2019

В Lambda есть некоторые низкие ограничения, особенно в Lambda @ Edge, на размер ответа.Ограничение составляет 1 МБ для всего ответа, включая заголовки и тело.Если лямбда-функция возвращает больший отклик, она будет усечена, что может вызвать состояние HTTP 500.См. документацию .

. Вы можете преодолеть это, сохранив изображение результата на S3 (или, возможно, сначала проверив, есть ли оно там), а затем вместо того, чтобы вернуть его, просто перенаправив 301 в дистрибутив CloudFront.интегрирован с этим контейнером - таким образом, запрос изображения будет перенаправлен на итоговое изображение.

Например, в node.js с триггером Origin-Response:

'use strict';
exports.handler = (event, context, callback) => {
    // get response
    const response = event.Records[0].cf.response;
    const headers = response.headers;

    // create image and save on S3, generate target_url
    // ...

    // modify response and headers
    response.status = 301;
    response.statusDescription = 'Moved Permanently';
    headers['Location'] = [{key: 'Location', value: target_url}]; 
    headers['x-reason'] = [{key: 'X-Reason', value: 'Generated.'}]; 

    // return modified response
    callback(null, response);
};

Версия для простого Lambda Gateway (без Origin-Ответ, заменяет заголовки):

exports.handler = (event, context, callback) => {
    // create image and save on S3, generate target_url
    // ...
    var response = {
      status: 301,
      headers: {
        Location: [{
          key: 'Location',
          value: [],
        }],
        'X-Reason': [{
          key: 'X-Reason',
          value: '',
        }],
      },
    };
    callback(null, response);
}
0 голосов
/ 22 марта 2019

Дополнительные примечания к ответу @ Zbyszek, вы можете приблизительно оценить, если запрос больше 1 МБ, например:

const isRequestBiggerThan1MB = (body, responseWithoutBody) => {
  const responseSizeWithoutBody = JSON.stringify(responseWithoutBody).length;
  return body.length + responseSizeWithoutBody >= 1000 * 1000;
};

responseWithoutBody не может быть слишком большим или содержать «рекурсивные ключи» (или чтоэто называется) но в этом случае я не могу себе представить, что у вас это будет.Если он содержит рекурсивные ключи, вы можете просто удалить их.Если responseWithoutBody слишком велик, вам нужно удалить эти значения и измерить их отдельно - например, как я делаю с response.body.

...