SNS直接发送到Lambda VS SNS发送到SQS再发送到Lambda

79

我正在尝试了解是否需要在我的工作流程中使用SQS,如果有人能够帮助解释一下。在我的应用程序中,当某个操作被执行时,它会向SNS主题提交信息,该主题会调用Lambda进行一些处理。这样做非常好。

当我在线上进行研究时,似乎人们也在这个堆栈中使用SQS,其中SNS会将信息放置在SQS上,然后SQS会调用Lambda。

我想我想要理解的是在这种情况下是否需要使用SQS。那样能够添加什么价值?换句话说,直接从SNS调用Lambda会有什么损失吗?


SQS是一种便宜且简单的队列服务,目前还没有触发能力。 - mootmoot
更新:现在SQS具有Lambda触发功能。 - best wishes
@bestwishes,然而,如果推送到SQS的数据量很少,那么就会导致NumberOfEmptyReceives问题。https://forums.aws.amazon.com/thread.jspa?threadID=296265 - Vishal Patel
6个回答

79
使用 SNS 和 Lambda 之间的 SQS 的主要优势是重新处理。假设 Lambda 由于某些原因(例如超时或缺乏内存占用)无法处理某些事件,您可以增加超时时间(最长为5分钟)或内存(最大为1.5GB),重新启动轮询并可以重新处理旧事件。
而在 SNS 到 Lambda 的情况下,这是不可能的,其中如果 Lambda 失败,则事件会丢失。即使您配置了 DLQ,仍然必须单独读取它并处理消息。
因此,如果您的事件很重要,不想错过它们,请选择 SNS - SQS - Lambda。
拥有 SQS 的另一个优势是节省 Lambda 调用成本(感谢 @codesinthedark 提出此点)。由于它允许您批量处理消息,因此您可以更好地进行扩展并减少成本。因此,在直接使用 SNS 的情况下,每个消息都会触发 Lambda 调用,而在一个 lambda 中可以执行一批10条消息。

1
在此重复一遍,而不是在下面作为另一个答案... AWS Lambda将Amazon Simple Queue Service添加到支持的事件源列表中 - dmulter
1
任何异步调用的 Lambda 函数都会重试两次,然后可以发送到 DLQ,该 DLQ 可以是 SNS 或 SQS。https://docs.aws.amazon.com/lambda/latest/dg/dlq.html 因此,在这个答案中给出的在 SNS 和 Lambda 之间添加 SQS 的原因是没有意义的。 - user3311298
2
我不同意这篇文章没有回答问题,因为假设您已经配置了DLQ而不是直接采用SQS的方法,那么对于所有失败的情况,您都必须转到DLQ。如果由于超时或内存足迹不足而导致故障,则我将不得不采取单独的措施来读取DLQ并处理消息,而如果在中间使用了SQS,则我只需重新配置带有更大内存足迹的lambda,其余的就会自动处理。 - Arafat Nalkhande
感谢指出DLQ。我对答案进行了轻微的调整,并添加了那部分内容。 - Arafat Nalkhande
6
我认为您忘记了使用Lambda和SQS而不是SNS的一个巨大好处。这样可以更好地扩展并减少成本,因为它允许您以批处理方式处理消息,因此一个Lambda函数可以处理10个消息,而每个SNS消息都会触发Lambda函数,并且在超过1000个msg/s时会失败或限流。您只需支付一个Lambda执行和一个SQS请求,而不是10个SNS请求。您可以更新您的回答。 - CodesInTheDark
显示剩余9条评论

9
我认为在2019年有一些变化,SQS可以通过事件源映射触发lambda函数,这是由@alexs提到的。相关博客文章:https://aws.amazon.com/about-aws/whats-new/2018/04/aws-lambda-now-supports-amazon-sqs-as-event-source/ 总之,您可以使用SQS将消息传递给lambda函数,有以下好处:
- 在失败时重新处理事件,并配置在放弃之前应重试多少次消息(接收计数)。 - 更长的保留期。 - 通常选择在需要运行时间较长的作业且lambda函数从作业队列中一个一个轮询的场景中使用。
如果您需要将单个消息复制到多个目标地址,请选择使用SNS:
- 如果您需要将单个消息复制到多个目标地址,则需要使用SNS。我认为这是最大的优点,如果您想要保证可靠性,可以将SNS和SQS配对使用。 - 如果您不关心丢失消息,请记住在使用SNS时仍然有重试策略(如线性、几何、指数等)。 - 通常用于可以更快地摄取/处理消息的情况下。但有时这也可能是个问题。请想象一种情况——您的企业每收到一封电子邮件就有一个SNS通知,但您没有足够的lambda并发处理所有的通知。您可以通过放置SQS来以自己的速度消费这些消息来解决这个问题。
在这两种情况下,都可能出现重复消息(在重试的情况下),且无法保证顺序。如果您需要保证顺序,请考虑使用Kinesis流。

2
2020年,随着SNS FIFO的推出,事情再次发生了变化——提供了严格的消息排序和去重的消息传递功能:https://aws.amazon.com/blogs/aws/introducing-amazon-sns-fifo-first-in-first-out-pub-sub-messaging/ - Jacek Kościesza
SNS的重试策略仅适用于由于消费者服务不可用而未收到消息的情况。如果您的Lambda无法正确处理消息,则可以将其配置为在默认情况下经过2次重试后将其消息发送到DLQ,但永远不会被发送回SNS进行重新传输。 - Scott Simontis

6

5

SQS不能调用Lambda函数,也无法调用其他任何东西。使用Lambda和SQS的人们会在事件计时器上运行Lambda,例如每分钟一次,并且每次函数运行时都会轮询SQS以查看是否有要处理的消息。

如果您不需要排队并防止过多Lambda函数同时运行,则不需要像SQS这样的队列系统。


抱歉,我想说的是当连接的SNS主题接收到任何信息时,LAMBDA会自动调用。这一直运作得很好。我想问的是,这种方法是否可扩展?例如,如果有数百个用户尝试执行该操作,那么在这种情况下使用SQS是否有所帮助,或者我的当前方法是否可以正常工作? - Saumil Shah
2
这完全取决于你的Lambda函数在做什么。如果它正在插入到有连接限制的关系数据库,或者访问具有速率限制的第三方API,则会遇到问题。如果它只是更新S3中的文件之类的东西,那么你可能不会遇到问题。您可能需要申请增加AWS帐户中允许的并发Lambda函数数量,但这就是全部了。 - Mark B
现在看起来SQS可以触发Lambda了,考虑到这个新功能,您的更新建议会是什么? - Davos
1
@Davos 如果你想控制并发和重试,添加SQS将是一个不错的选择。但这会增加一些成本。 - Mark B
@Davos 是的,SQS 现在有一个 Lambda 触发器,但内部 Lambda 会轮询 SQS。因此你不必手动触发 Lambda 事件来轮询消息。 - Vishal Patel

5

除了 @Arafat Nalkhande 的回答之外,以下是 SQS 的 Lambda 的一些好处:

  1. 在 SQS 中我们可以设置一个 延迟,以便消息在一段时间后被处理,这可能在数据需要花费一些时间才能可用的情况下很有用。

  2. SQS 可以作为一个备用存储,假设下游服务不可用,消息可以在 SQS 中保留 15 天。


0

这取决于您想如何处理重试和错误处理。每个AWS资源都有一种方法来重试失败的事件,因此您需要了解SNS如何处理失败的事件,它是否能够处理它或者如果不能,则使用SQS。但是,您始终可以将失败的事件从lambda推回SNS,以便再次处理它们。但还要考虑您是否真正需要SQS,即您真正需要队列服务,而不仅仅是为了重试,因为您始终可以使用其他方式来处理此类问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接