我有一个 Lambda 函数,其并发数固定为 1,其 SQS 触发器配置为batchSize
10。此 Lambda 函数仅将其遇到的内容发布到 SNS 主题(代码只有几行)。我使用它来限制收到的大量消息,以便我的后端可以顺利处理它们。
理论上,这个 Lambda 永远不应该向 SQS 的死信队列发送任何消息,但 80% 的消息最终都在那里!我不明白为什么,因为 Lambda 日志显示没有任何执行失败。没有抛出任何异常,日志中只显示成功的执行。
Lambda 在什么时候决定某条消息应该进入死信队列?(我的重新驱动策略的最大接收数量为 3)。
答案1
没有直接回答你的问题,但是为什么你的后端轮询 SQS并按照自己的节奏一次处理一条消息?这将是一个更常见的模式。
你也可以扩展后端根据 SQS 队列深度添加更多节点来处理(如果适用)。如果您的消息在工作时间到达的频率更高,而在晚上到达的频率更低,那么您的后端应该能够在较安静的时间赶上消息流。
或者,如果你只对最新消息感兴趣,你可以设置到期时间大约 1 分钟后,消息将从队列中消失,并且您的后端将检索最新的消息。
我认为这是一个比尝试限制通过 Lambda 到 SNS 的消息速率并希望后端能够跟上更好的架构。
如果做后端的 SQS 轮询不可能让我们知道,我们将重新审视您的 Lambda / DLQ 问题;)
希望有帮助:)
答案2
听起来你是不删除处理后在 Lambda 函数中检索到的消息。
我认为会发生以下情况:
- 消息 M1 到达 SQS,
- 您的 Lambda 会将其拾取、发送到 SNS、不会将其从 SQS 中删除并退出。
- 过了一会儿(之后默认可见性超时=30s)相同的消息M1被重新插入到队列中,因为它被检索到但在处理后没有被删除。
- 这种情况会发生 3 次(由于您的 Redrive 策略),然后它会被发送到死信队列。
最终,所有消息都会因此进入 DLQ。
我对吗? :)
答案3
另一个想法 - 由于 SQS 中消息的有效期最多为 4 天,因此您可以有一些轮询 SQS 的过程以某个可持续的速率(由您的 RDS 吞吐量决定)并重新发送到 SNS。过程将实现所需的限制 - 保留上一分钟处理的消息计数器,并延迟下一次 SQS 轮询,直到吞吐量低于限制。简单的滑动窗口算法应该可以解决问题。您可能会从中获得一些启发网络速率限制其目标是一样的——限制接收者的吞吐量。
这将比SQS 触发的 Lambda并尝试通过并发性和批量大小限制来限制它 - 这种方法可能具有相当不可预测的吞吐量配置文件。
您可以在长期运行的 Lambda 中进行轮询(我认为每次运行最多 10 分钟),或者更好的方法是将其作为 Fargate 或 ECS 上运行的容器中的服务。无论哪种方式更便宜。
这能算是一个答案吗?
答案4
Julian,尽管 lambda 没有任何错误或超时,但消息最终还是进入了 DLQ因为 lambda 被限制了。
解决您的问题的一个可能方法是使用队列的最大并发值,这是几个月前才推出的设置。请参阅使用 Amazon SQS 作为事件源时引入 AWS Lambda 函数的最大并发性。