AWS - 在 SNS 订阅或 Lambda 函数上设置死信队列有啥区别?

Posted

技术标签:

【中文标题】AWS - 在 SNS 订阅或 Lambda 函数上设置死信队列有啥区别?【英文标题】:AWS - What is the difference between setting a Dead Letter Queue on an SNS Subscription or on a Lambda function?AWS - 在 SNS 订阅或 Lambda 函数上设置死信队列有什么区别? 【发布时间】:2020-12-12 10:32:02 【问题描述】:

在 SNS 主题或 Lambda 函数上设置死信队列有什么区别?

我想知道,因为如果您在 SNS 订阅上设置 DLQ,那么当 Lambda(订阅者)失败时,该订阅消息将故障转移到 DLQ,对吗?那么在那种情况下,在这两个地方设置DLQ会产生同样的效果吗?

我在 SNS 主题订阅上设置了 DLQ,但它并没有“自动”显示为 Lambda 屏幕设置中的 DLQ,所以我认为可能存在一些差异?

SNS 死信队列参考:https://docs.aws.amazon.com/sns/latest/dg/sns-dead-letter-queues.html

通常,当 Amazon SNS 由于客户端或服务器端错误而无法访问订阅的终端节点时,消息传递会失败。

Lambda 死信队列参考:https://aws.amazon.com/about-aws/whats-new/2016/12/aws-lambda-supports-dead-letter-queues/

在标准重试策略(失败时额外重试 2 次)用尽后,AWS Lambda 将调用 Lambda 函数的事件对象写入此 [DLQ] 端点。

拉姆达:

SNS 订阅:

【问题讨论】:

【参考方案1】:

SNS DLQ 是特定于 SNS 的,这里的好处是它还考虑了客户端错误,例如 Lambda 服务关闭。这将确保如果 Lambda 服务关闭,消息可以稍后重播给它,而如果 DLQ 附加到 Lambda,这只会在服务正在运行时才考虑重播。

但是,正如我提到的,SNS DLQ 仅适用于来自 SNS 的通知,而 Lambda 可以支持来自任何传入事件的 DLQ。这意味着如果您有多个 SNS 主题,或者一个 SNS 主题和一些 SQS 队列,您只需将其应用于 Lambda 本身。

两个服务都将 SQS 用于其 DLQ,因此来自两者的摄取/检索将是相同的。如果您在这两个服务上都有 DLQ,那么是的,您最终可能会获得 2 个事件/通知副本,但是您不太可能同时获得这两个副本,因为理论上 Lambda 端点会承认 SNS 将其视为已发送,那么这将如果 DLQ 失败,则由 Lambdas 负责添加。

【讨论】:

这很有道理,谢谢,因此 DynamoDB 事件之类的事情可以由 Lambda DLQ 重放。澄清一下,如果 Lambda 在收到 SNS 消息后崩溃,是否会触发 SNS DLQ?即 SNS 需要 Lambda 的成功响应以确认 SNS 消息已被消耗,对吗? Lambdas 状态的文档“对于异步调用,Lambda 将消息排队并处理重试。如果 Amazon SNS 无法到达 Lambda 或消息被拒绝,Amazon SNS 会在几个小时内以增加的间隔重试. 有关详细信息,请参阅 Amazon SNS 常见问题中的可靠性。”。如果 Lambda 服务失败或您通过回调拒绝,它将非常有效地重试,我会假设添加到 SNS 的 DLQ。 太好了,我猜想抛出未捕获异常的 Lambda 也算作拒绝。 :+1:【参考方案2】:

SNS DLQ 和 Lambda DLQ 保护您的工作负载免受不同故障模式的影响。前者用于主题的消息传递失败,而后者用于功能执行失败。您应该同时使用两者。更多信息:https://aws.amazon.com/blogs/compute/designing-durable-serverless-apps-with-dlqs-for-amazon-sns-amazon-sqs-aws-lambda/

【讨论】:

是的,但是有重叠,如果 Lambda 崩溃,SNS 队列可以通知消息传递失败。所以如果你同时设置,你会得到两个死信(这不是一件完全坏事,但应该知道)。 并非如此。这两种故障模式是互斥的。因此,您的 SNS 交付失败(SNS DLQ 捕获)或您的 Lambda 执行在接受 SNS 交付(您的 Lambda DLQ 捕获)后失败。这就是为什么我建议同时配置 SNS DLQ 和 Lambda DLQ。 我认为成功执行后接受消息传递 没有。向 Lambda 的 SNS 传递是异步的。因此,SNS 传递可以成功,然后 Lambda 执行可能会失败。

以上是关于AWS - 在 SNS 订阅或 Lambda 函数上设置死信队列有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

AWS lambda 发送 SNS“成功”但未实际发送消息

我可以触发 Lambda 函数或 SNS 事件来响应 AppSync GraphQL 突变吗?

使用 AWS Lambda 观看 SNS 主题并通过 websocket 交付?

如何使用AWS Lambda和SNS事件触发Spring Cloud功能的重试

OpsGenie 不会在 AWS 仪表板或 terraform 中自动确认 SNS 订阅

使用AWS Lambda从AWS SNS读取时修改JSON消息