AWS SQS 异常“413 请求实体太大”

问题描述

我已经被困了一段时间来弄清楚下面的异常,任何帮助都会得到回报。 我们在 Laravel 项目上使用 AWS Lambda 服务。我们正在使用 Laravel Excel 将大量数据导出到 CSV 文件,我们通过 Laravel SQS 队列执行此操作。

PHP 版本:7.2
Laravel 框架:7.30.1
Laravel Excel:3.1

异常:

Aws\Sqs\Exception\SqsException /tmp/vendor/aws/aws-sdk-PHP...
stage.ERROR: Error executing "SendMessage" on "https://sqs.eu-central- 
1.amazonaws.com"; AWS HTTP error: Client error: `POST https://sqs.eu- 
central-1.amazonaws.com/` resulted in a `413 Request Entity Too Large` 
response:
HTTP content length exceeded 1662976 bytes.
Unable to parse error information from response - Error parsing XML: String Could not be parsed as 
XML {"exception":"[object] (Aws\\Sqs\\Exception\\SqsException(code: 0): Error executing      
\"SendMessage\" on \"https://sqs.eu-central-1.amazonaws.com/"; AWS 
HTTP error: Client error: `POST https://sqs.eu-central-1.amazonaws.com/` resulted in a `413 Request Entity Too Large` response:
HTTP content length exceeded 1662976 bytes.
Unable to parse error information from response - Error parsing XML: String Could not be parsed as 
XML at /tmp/vendor/aws/aws-sdk-PHP/src/WrappedHttpHandler.PHP:195)
[stacktrace]

解决方法

来自docs

消息大小
最小消息大小为 1 字节(1 个字符)。最大为 262,144 字节 (256 KB)。

我的猜测是您尝试发送的文件大于 256KB,这是 AWS 中 SQS 消息的硬限制。

输出 HTTP content length exceeded 1662976 bytes 表明我的猜测可能是正确的。

这种情况下的常见模式是将文件上传到 S3 并通过队列发送对对象的引用。

,

场景
AWS docs 发送数据到 SQS 队列的硬限制是 256KB。发生这种情况是因为我将 Collection 对象发送到 SQS 队列,并且每个对象都有多个 Eager Loading 关系,因此对象大小变得太大。

AWS 解决方案
将集合对象数组中的 id 传递给 SQS 队列有助于解决 Entity Too Large 问题。

Excel 解决方案
我没有使用 Laravel Excel,而是使用 Laravel Storage append 方法将行添加到我的 csv 文件中。我已经用 50k 行测试过,效果很好。不要一次处理所有行,您可能会遇到 AWS timeout 异常,我相信每个队列是 15 minutes