6

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

如果您要求:所见即所得/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。

4

2 回答 2

7

Lambda 有一些下限,尤其是在 Lambda@Edge 中的响应大小。整个响应、标头和正文的限制为 1 MB。如果 lambda 函数返回更大的响应,它将被截断,这可能导致 HTTP 500 状态。请参阅文档

您可以通过在 S3 上保存结果图像(或者可能首先检查它是否已经存在)来克服这个问题,然后不再返回它,而是将 301 重定向到与该存储桶集成的 CloudFront 分配 - 因此图像请求将被重定向到结果图像。

例如在带有 Origin-Response 触发器的 node.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);
}
于 2019-03-19T21:22:37.037 回答
1

@Zbyszek 回答的附加说明,您可以大致估计请求是否大于 1MB,如下所示:

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

responseWithoutBody 不能太大或包含“递归键”(或所谓的),但在这种情况下,我无法想象你会拥有它。如果它包含递归键,那么您可以简单地删除它们。如果 responseWithoutBody 太大,您需要删除这些值并单独测量它们 - 例如,就像我对 response.body 所做的那样。

于 2019-03-22T10:32:50.257 回答