为什么 SQS 直到可见性超时之后才将消息发送到死信队列?

huangapple go评论68阅读模式
英文:

Why is SQS not sending message to dead letter queue until after visibility timeout?

问题

我已配置了一个作为Lambda触发器的AQS SQS。这个SQS还配置为将无法处理的消息发送到我设置的死信队列。我已将最大接收次数设置为1,因为这是最小值,将触发队列的可见性超时设置为5分钟。我的意图是不进行任何重新处理。如果来自触发队列的消息失败,我希望它立即进入DLQ。我理解的是,如果我的Lambda中抛出了异常,即使可最大接收次数设置为最低值(在此情况下为1),消息也会在可见性超时之前等待5分钟,然后才移动到DLQ。是否有任何方法在出现异常时立即移动它,而不考虑可见性超时?谢谢。

英文:

I have an AQS SQS configured as a trigger for a Lambda. This SQS is also configured to send unprocessable messages to a Dead Letter Queue I setup. I have set the Maximum Receives to 1 as that is the minimum and the visibility timeout on my trigger queue to 5 minutes. My intent is to have 0 reprocessing. If the message from the trigger queue fails I want it to go to the DLQ right away. My understanding was that if an exception was thrown in my lamdba that it would send it to the DLQ immediately if the Maximum Receives was set to lowest (1 in this case), regardless of the visibility timeout. However it seems even if I throw an exception, the message still waits the full 5 minutes before then moving to the DLQ. Is there any way to get it to move immediately on exception regardless of visibility timeout? Thanks.

答案1

得分: 0

"我原本以为,如果我的Lambda函数中抛出了异常,它会立即发送到DLQ" - 不是这样的。

SQS不知道您的Lambda函数(或任何其他处理方式)是否失败或抛出异常。只有在可见性超时到期后,SQS才会考虑消息处理失败,并且只有在那时它才会将消息放入DLQ。

SQS不知道或关心其消费者如何处理消息,例如,它们是否在内部重试,总是在最后一刻才删除消息,从不删除消息,在实际处理消息之前删除消息等等。因此,当消费者失败时,SQS无法采取任何操作,因为SQS根本不知道消费者失败的样子。而且对于SQS来说,是否出现了任何实际的失败情况也不清楚,也许消费者只是花费太长时间来处理消息,SQS并不关心。


而且,不,您不能合理地更改这种行为。您可能可以在您的Lambda函数实际抛出异常之前手动更改一个消息的可见性超时(请参阅ChangeMessageVisibility),或者您可以删除消息并手动将其发送到DLQ(非常不好的做法/实践)。这两种方法都需要手动操作,更重要的是需要您的Lambda函数意识到自己的异常,捕获所有异常,执行一些SQS操作,然后重新抛出异常 - 这保证会以某种方式出现问题...

英文:

"My understanding was that if an exception was thrown in my lamdba that it would send it to the DLQ immediately" - No.

SQS does not know about your lambda (or any other processing for that matter) failing or throwing an exception. Only after the visibility timeout expires can SQS consider the message processing to have failed and only then can it put the message into the DLQ.

SQS does not know or care how its consumers handle the message, if they e.g. retry internally, always delete the message at the last possible second, never delete a message, delete the message before actually working on it, etc. And therefore SQS cannot take any actions when the consumers fail because SQS simply does not know what a consumer failing looks like. And it is also not clear to SQS if anything actually failed, maybe the consumer simply took too long to process the message, SQS does not care.


And no, you cannot reasonably change that behaviour. You might be able to change the visibility timeout of the one message manually right before your lambda actually throws the exception (see ChangeMessageVisibility) or you could delete the message and manually send it to the DLQ (very bad idea / practise). Both approaches require manual work and more importantly require your lambda to be aware of its own exception, catch all exceptions, do some SQS stuff and then rethrow the exception - this is guaranteed to go wrong in some way...

huangapple
  • 本文由 发表于 2023年6月22日 19:42:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531525.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定