SQS Lambda-重试逻辑?

时间:2018-09-30 19:57:57

标签: node.js aws-lambda amazon-sqs

将消息添加到SQS队列中并将其配置为触发lambda函数(nodejs)时。

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

如何用node 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函数。

4 个答案:

答案 0 :(得分:4)

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

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

SQS Queue Attributes

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

如果您只想尝试3次,则必须设置SQS重新驱动策略(又称为“死信队列”)

Dead Letter Queue Settings

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

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

  1. 已处理,没有任何错误(lambda删除了邮件)
  2. $group = "NewUsers" Get-ADUser -SearchBase 'cn=users,dc=costco,dc=com' -Filter { whenCreated -ge $When } | %{ Add-ADGroupMember -Identity $Group -Members $_.samaccountname } 过期(SQS删除邮件)
  3. 它被发送到SQS队列重新驱动策略中设置的DLQ(SQS将消息“移动”到DLQ)
  4. 您直接在代码中从队列中删除了消息(用户删除了消息)

否则Lambda不会处理此错误消息。


重要观察

Lambda不会处理失败的消息

基于几次实验,我了解了SQS集成的行为(重试中的documentation是模棱两可的ATM),lambda不会删除失败的消息并将继续重试它们。即使已设置Lambda DLQ,消息也不会发送到DLQ,它完全依赖于lambda DLQ documentation中所述的SQS队列的配置。

推荐

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

异常将使整批消息失败

正如我之前所说,如果在处理消息时代码中有异常,则将重试整批消息,某些消息是否正确处理并不重要。如果由于某种原因下游服务失败,您最终可能会看到在DLQ中处理的消息。

推荐

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

Lambda并发限制和SQS副作用

博客文章“ Lambda Concurrency Limits and SQS Triggers Don’t Mix Well (Sometimes)”描述了如何在并发限制设置得太低的情况下,lambda导致大量邮件被限制,接收尝试从未增加过正在处理。

推荐

该帖子和亚马逊的建议是:

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

答案 1 :(得分:3)

这是我的方法。

  1. 创建普通队列(立即交付),第一季度
  2. 第二季度创建延迟队列(延迟5分钟)
  3. 创建DLQ(重试后),DLQ1
  

(Q1 / Q2)SQS触发器-> Lambda L1(如果失败,请在(Q1 / Q2)上删除,然后放下   它在第二季度)->在失败DLQ上

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

如果您的初始消息可能会延迟5分钟,那么您可能不需要两个队列。一个队列应该很好。如果初始延迟不可接受,则需要两个队列。拥有两个队列的另一个原因是,您将始终有一种方法来获取路径中出现的新消息。

如果在处理Q1 / Q2时遇到代码故障,则AWS基础结构将立即重试3次,然后再将其发送到DLQ1。如果您处理了代码中的错误,则可以使管道与您提到的时间一起使用。

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 希望对您有所帮助。

答案 2 :(得分:2)

非常简单,无需进行任何编码。首先:如果您的代码将引发错误,AWS Lambda将重试3次以上以执行您的代码。在这种情况下,如果无法访问外部API,则AWS会在第三次重试时进行很大的更改–该API可以使用。再加上重试之间的延迟是随机的,这意味着重试之间存在延迟。

如果最糟糕的情况发生了,并且外部API尚未启动,则可以利用每个lambda所具有的死信队列(DLQ)功能。这将向SQS推送一条消息,指出出了什么问题,因此您可以采取其他措施。在这种情况下,请继续重试,直到成功。

您可以在此处了解更多信息:https://docs.aws.amazon.com/lambda/latest/dg/dlq.html

答案 3 :(得分:1)

根据此博客:

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

  

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