Lambda @ Edge仅针对某些图像提供502

时间:2019-03-08 13:32:43

标签: amazon-cloudfront aws-lambda-edge

我们要做的是请求一个图像,例如“ media / catalog / product / 3/0/30123 / 768x / lorem.jpg”,然后我们使用位于“ media / catalog / product / 3”的原始图像/0/30123.jpg”,如果浏览器支持,则将其调整为768px和webp,然后返回新图像(如果尚未缓存)。

如果您请求:wysiwyg / lorem.jpg,它将尝试创建最大1920像素(不放大)的webp。

在小于等于1420像素的图像上,这似乎可以很好地工作。但是,在此之上,我们只会得到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可能会导致误导,因为那为什么为什么它适用于较小的图像?我们在Cloudfront中禁用了GZIP。

我为Lamda @ Edge Resize函数提供了3GB的最大资源,并具有30秒的超时时间。对于大图像来说,这还不够吗?

我已经删除了已经生成的图像,使Cloudfront无效,但其行为仍然相同。

编辑:更新

我只是尝试了一个不同的图像,然后它就可以正常工作。。我不知道为什么以及如何解决损坏的图像……我想Cloudfront现在已经将502缓存了。 “,但没有帮助。两个原始文件均为jpg。

有效的原始源映像为6.1 MB,如果无效,则为6.7 MB。

它们具有以下限制: https://docs.aws.amazon.com/lambda/latest/dg/limits.html

response.body停止工作时约为512 MB。

2 个答案:

答案 0 :(得分:1)

Lambda有一些较低的限制,尤其是在Lambda @ Edge的响应大小上。整个响应(包括标头和正文)的限制为1 MB。如果lambda函数返回更大的响应,它将被截断,这可能会导致HTTP 500状态。参见documentation

您可以通过以下方法解决此问题:将结果图像保存在S3上(或者先检查是否已经存在),然后返回301重定向到与该存储桶集成的CloudFront分发,而不是返回它-因此图像请求将被重定向到结果图像。

例如在具有Origin-Response触发器的nod​​e.js中:

'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网关的版本(无Origin-Response,替换标头):

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);
}

答案 1 :(得分:0)

@Zbyszek答案的其他说明,您可以像这样大致估算请求是否大于1MB:

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

responseWithoutBody不能太大或包含“递归键”(或所谓的“递归键”),但是在这种情况下,我无法想象您会拥有它。如果它包含递归键,则只需将其删除即可。如果responseWithoutBody太大,则需要删除这些值并分别进行测量-例如,就像我在使用response.body一样。