SQS Lambda - 重试逻辑?

问题描述 投票:5回答:4

当消息已添加到SQS队列并且配置为触发lambda函数(nodejs)时。

当触发lambda函数时 - 我可能想在5分钟后再次重试相同的消息而不从队列中删除消息。如果Lambda无法连接外部主机(例如:API),我想这样做的原因 - 我想在5分钟后再次尝试3次尝试。

如何在节点js中编写?

例如在Laravel中,我们可以使用Specifying Max Job Attempts功能。使用public $tries = 5;尝试作业的次数

资料来源:https://laravel.com/docs/5.7/queues#max-job-attempts-and-timeout

我们怎样才能在node.js中做类似的方式?

我正在考虑将消息添加到另一个队列(用于重试)。 lambda函数在5分钟后读取该队列中的所有消息,并将该消息发送回主队列,它将触发lambda函数。

node.js aws-lambda amazon-sqs
4个回答
3
投票

我就是这样做的。

  1. 创建正常队列(即时交付),Q1
  2. 创建延迟队列(延迟5分钟),Q2
  3. 创建DLQ(重试后),DLQ1

(Q1 / Q2)SQS触发 - > Lambda L1(如果失败,删除(Q1 / Q2),将其丢弃在Q2) - >失败DLQ

当消息到达Q1时,如果从那里成功,则触发Lambda L1。如果失败,则将其丢弃到Q2(这是一个延迟队列)。到达Q2的每条消息都会有5分钟的延迟。

如果您的初始消息可能有5分钟的延迟,那么您可能不需要两个队列。一个队列应该是好的。如果初始延迟不可接受,那么您需要两个队列。拥有两个队列的另一个原因是,您始终可以使用路径中的新消息。

如果在处理Q1 / Q2时代码失败,aws基础设施将在将其发送到DLQ1之前立即重试3次。如果您在代码中处理错误,那么您可以使用管道来处理您提到的时间。

SQS延迟队列:

https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-delay-queues.html

SQS Lambda架构:

https://nordcloud.com/amazon-sqs-as-a-lambda-event-source/

enter image description here希望它有所帮助。


8
投票

重新尝试和重新尝试“超时”都可以直接在SQS队列中配置。

创建队列时,请设置以下属性:

SQS Queue Attributes

默认可见性超时将是应用程序收到邮件后隐藏的时间。如果消息在lambda运行期间失败并且抛出异常,则lambda将不会删除批处理中的任何消息,并且所有消息最终将重新出现在队列中。

如果您只想尝试3次,则必须设置SQS重新启动策略(AKA死信队列)

Dead Letter Queue Settings

重新驱动策略将使您的队列在消息重新出现在队列N次数后将消息重定向到死信队列(DLQ),其中N是1到1000之间的数字。

必须了解lambda将继续处理失败的消息(在代码中生成异常的消息),直到:

  1. 处理没有任何错误(lambda删除消息)
  2. Message Retention Period到期(SQS删除消息)
  3. 它被发送到SQS队列重新驱动策略中设置的DLQ(SQS将消息“移动”到DLQ)
  4. 您可以直接在代码中删除队列中的消息(用户删除消息)

否则Lambda不会处理这个坏消息。


重要观察

Lambda will not deal with failed messages

根据几个实验,我试图了解SQS集成的行为(documentation重试是模糊的ATM),lambda不会删除失败的消息,并将继续重新尝试它们。即使你设置了Lambda DLQ,消息也不会被发送到DLQ,它完全依赖于为此目的配置SQS队列,如lambda DLQ documentation中所述。

建议:

  • 始终在SQS队列中使用重新驱动策略。

Exceptions will fail a whole batch of messages

正如我之前所说,如果在处理消息时代码中存在异常,则会重新尝试整批消息,如果某些消息处理得当,则无关紧要。如果由于某种原因下游服务失败,您可能最终会看到在DLQ中处理的消息。

建议:

  • 手动删除已正确处理的邮件
  • 确保lambda函数可以多次处理相同的消息

Lambda concurrency limits and SQS side effects

博客文章“Lambda Concurrency Limits and SQS Triggers Don’t Mix Well (Sometimes)”描述了如果您的并发限制设置得太低,lambda可能会导致批量消息被限制,并且接收的尝试将被递增而不会被处理。

建议:

帖子和亚马逊的推荐是:

  • 将队列的可见性超时设置为您在函数上配置的超时的至少6倍。
  • 如果在函数处理上一批时函数执行被限制,则额外时间允许Lambda重试。
  • 将队列的重启策略中的maxReceiveCount设置为至少5.这将有助于避免由于限制而将消息发送到死信队列。
  • 配置死信以保留失败的消息足够长的时间,以便稍后可以将它们移回以进行重新处理

2
投票

相当简单,无需进行任何编码。首先:如果您的代码会抛出错误,AWS Lambda将重试3次以执行您的代码。在这种情况下,如果外部API无法访问,那么在第三次AWS重试时会发生重大变化 - API将起作用。再加上重试之间的延迟是随机意义,重试之间存在延迟。

如果最坏的情况发生,并且外部API尚未启动,您可以利用每个lambda具有的死信队列(DLQ)功能。哪个会向SQS发送一条消息,说明出了什么问题,以便您可以采取其他措施。在这种情况下,请继续重新尝试直到您完成它。

你可以在这里阅读更多:https://docs.aws.amazon.com/lambda/latest/dg/dlq.html


1
投票

根据这篇博客:

https://www.lucidchart.com/blog/cloud/5-reasons-why-sqs-lambda-triggers-are-a-big-deal

利用现有的重试逻辑和死信队列。如果Lambda函数未返回成功,则不会从队列中删除该消息,并且在可见性超时到期后将重新显示该消息。

© www.soinside.com 2019 - 2024. All rights reserved.