我们有一些由 SQS 队列触发的 Lambda。Lambda 会对 DynamoDB 表进行大量插入。DynamoDB 表具有自动扩展写入容量。
在峰值负载下,大量消息会发送到 Lambdas,它们会开始因 ProvisionedThroughputExceededException 而失败。DynamoDB 需要几分钟才能扩展。
我们预计,当 Lambda 失败时,消息将返回到 SQS,并在可见性超时后再次处理。这看起来是正确的,因为稍后 DynamoDB 会扩展,并且应该能够处理增长的写入。
然而,我们发现一个奇怪的现象,当 Lambda 执行错误的数量增加时,SQS 触发器会自动禁用,Lambda 停止执行,消息会累积在队列中。
手动启用触发器会导致更多失败,因为 DynamoDB 仍未扩大规模,但从队列中处理的消息数量急剧增加。
只有手动增加 DynamoDB 的写入容量才有帮助。
为什么 SQS 触发器会禁用?此行为没有记录。
如何避免触发器禁用?
一般来说,建议采用哪种“背压”来限制 Lambda 从 SQS 轮询消息的速度?
答案1
我不确定 Lambda 为何停止工作。我怀疑 Lambda 服务注意到它不断失败,因此暂时将其暂停。不确定。
您可以尝试多种解决方法:
- 使用DynamoDB 按需容量- AWS 表示它可以立即扩展。
- 或者,如果您使用预配置容量并获得预配置吞吐量异常实际上不会中止 Lambda 执行,而是将消息重新插入 SQS 队列并成功退出。这样,Lambda 服务就不会出现任何故障,也不会丢失任何 SQS 消息。
以下方法可能会有帮助:)
答案2
AWS 支持表示,由于 Lambda 执行角色的权限不足,触发器可能会被禁用。
我的问题:
Lambda 触发器自动禁用的条件记录在哪里?或者在哪里可以找到触发器被禁用的原因(某种 Lambda 服务日志)?
AWS 支持人员回答:
目前,还没有公开的文档提到 Lambda 触发器被自动禁用的可能原因。但是,正如我前面提到的,SQS Lambda 触发器被禁用的最可能原因是 Lambda 函数执行角色没有以下一个或多个必需的权限:
- sqs:ChangeMessageVisibility
- sqs:删除消息
- sqs:获取队列属性
- sqs:接收消息
- 访问相关的KMS密钥
- 任何适用的跨账户权限
- 此外,如果 lambda 函数在 VPC 中,则 Lambda 函数应该具有列出、创建和删除 ENI 的所有权限
此外,Lambda 函数日志中不会提及禁用触发器的原因。因此,我请求您确保 Lambda 函数执行角色具有所有必需的权限。如果 Lambda 函数执行角色具有所有必需的权限,则 SQS 触发器不应自动被禁用。
就我而言,我们实际上错过了 VPC 权限,即我们没有将AWSLambdaVPCAccessExecutionRole
策略附加到 Lambda 执行角色。(我不知道没有这个策略 Lambda 如何工作)。自从我们修复角色以来已经过去了五天,没有禁用任何触发器。所以,它起作用了。
至于 DynamoDB 和“背压”,MLu的理念是正确的。
如果每条 SQS 消息只向 DynamoDB 写入一次,则写入失败时 Lambda 可能会失败。消息将保留在 SQS 中,并在可见性超时后再次被 Lambda 接收。在这种情况下,最好使用批处理大小 1 来逐条处理消息。
如果每条 SQS 消息都对 DynamoDB 进行多次写入(写入乘法),最好ProvisionedThroughputExceededException
在 Lambda 中捕获失败的写入,并延迟将失败的写入放入另一个队列,以便稍后由另一个 Lambda 重复执行。请注意,重复每次写入很重要,而不是重复原始消息。
数据流将会像这样:
请注意,任何延迟重复写入只有在您确实可以延迟和重复写入的情况下才是可以接受的。它们应该是幂等的,并且不应包含实时数据。否则,最好默默忽略任何异常,以避免 Lambda 失败,然后从 SQS 中删除并忘记该消息。