AWS Lambda - Body Size is Too Large 错误,但 Body Size is Under Limit

AWS Lambda - Body Size is Too Large Error, but Body Size is Under Limit

我正在使用 lambda 函数为 REST API 提供服务。在一个端点中,我将“body size is too long”打印到 cloudwatch 日志中。

我从该函数得到的响应是状态代码 502,响应正文为 {“消息”:“内部服务器错误”}。如果我调用同一个端点但使用过滤器,则响应正文大小为 2.26MB 并且有效。这排除了我达到异步响应正文限制的可能性。

出错时的响应体大小为5622338字节(5.36MB)。

这就是我计算响应大小的方式 (python 2.7):

import urllib2
...

out = {}
resp = urllib2.urlopen(req)
out.statusCode = resp.getcode()
out.body = resp.read()
print("num bytes: " + str(len(bytearray(out.body, 'utf-8'))))

同步调用的广告最大响应正文大小为 6MB。据我了解,我不应该收到错误。 https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

其他信息:

持续时间:22809.11 毫秒计费持续时间:22810 毫秒内存大小:138 MB 使用的最大内存:129 MB 初始化持续时间:1322.71 毫秒

如有任何帮助,我们将不胜感激。


21 年 4 月 22 日更新

经过进一步研究,我发现如果响应大小为 1,048,574 字节 (0.999998 MB) 或更多,lambda 函数就会出错。

如果响应为 1,048,573 字节 (0.999997 MB) 或更少,则它有效。

这就是我return回应的方式。我将视图函数硬编码为 return 特定大小的字节数组。 例如

return bytearray(1048573)

我为正在使用的 AWS Gateway Stage 打开了日志记录,但以下错误正在写入日志。这意味着该功能正在出错。不是函数的调用: 由于客户功能错误,Lambda 执行失败,状态为 200:主体尺寸太长。

据我了解,AWS Lambda 函数的最大响应大小为 6MB,AWS 网关的最大响应大小为 10MB。

AWS Lambda:调用负载响应 https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

API 网关:API 配置和 运行 REST API -> 负载大小的网关配额 https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html

我是不是误解了限制?

我为 python 3.7 创建了一个新的 lambda 函数,发现它 return 是一个更具描述性的错误。我能够确定 lambda 函数在离开 lambda 函数后将响应大小增加了大约 1 MB,这解释了为什么它在 lambda 函数中出错,但在端点代码中没有出错。在一种情况下,它增加了 .82MB,在另一种情况下,它增加了 .98MB。它似乎是基于响应的大小。我怀疑响应正在进行 base64 编码、URL 编码或类似的编码。我没有找到可以回答这个问题的文档,并且响应在接收端没有以任何方式编码。

错误消息 return 由使用 python 3.7 构建的 lambda 函数编辑:

响应负载大小(8198440 字节)超过了允许的最大负载大小(6291556 字节)。

Lambda 函数代码:

import requests, base64, json

def lambda_handler(event, context):
    
    headers = {...}
    url = ...
    
    response = requests.get(url, headers=headers)
    
    print (len(response.content))
    print (len(response.content.decode("utf-8")))

    
    return response.content.decode('UTF-8')

下面是在 lambda 函数中打印时的响应大小以及错误消息中由 lambda 确定的响应大小。

我使用这两个打印语句来确定响应的大小,并且这两个打印语句总是 return 相同的长度。 Response.content 是一个字节数组,所以我的思考过程是获取它的长度将 return 响应中的字节数: 打印 (len(response.content)) 打印 (len(response.content.decode("utf-8")))

例 1.

在 lambda 函数内打印时的大小:

7,165,488 (6.8335 MB)

错误消息中定义的大小:

8,198,440 (7.8186 MB)

额外:

1,032,952 (0.9851 MB)

错误信息:

响应负载大小(8198440 字节)超过了允许的最大负载大小(6291556 字节)。

例 2. 在 lambda 函数内打印时的大小:

5,622,338 (5.3619 MB)

错误消息中定义的大小:

6,482,232 (6.1819 MB)

额外:

859,894 (0.820059 MB)

错误信息:

响应负载大小(6482232 字节)超过了允许的最大负载大小(6291556 字节)。

我已决定将端点代码中的软限制再降低 1 MB (4.7MB),以防止达到 lambda 函数中的限制。

在 golang 中尝试了同样的方法。 events.APIGatewayV2HTTPResponse.Body 可以是 ~5.300.000 字节(没有测试确切的限制)。值是在 lambda 函数内测量的 (len(resp.Body))