45

我有一个基于服务的应用程序,它使用带有多个队列和多个使用者的 Amazon SQS。我这样做是为了实现基于事件的架构并解耦所有服务,其中不同的服务对其他系统的状态变化做出反应。例如:

  • 注册服务
    • 新用户注册时发出事件“registration-new”。
  • 用户服务
    • 更新用户时发出事件“用户更新”。
  • 搜索服务
    • 从队列“registration-new”中读取并在搜索中索引用户。
    • 从队列“用户更新”中读取并更新搜索中的用户。
  • 指标服务
    • 从“registration-new”队列中读取并发送到 Mixpanel。
    • 从队列“用户更新”中读取并发送到 Mixpanel。

我有很多问题:

  • 轮询时可以多次收到一条消息。我可以将很多系统设计为幂等的,但对于某些服务(例如指标服务)而言,这将更加困难。
  • 需要从 SQS 的队列中手动删除一条消息。我曾想过实现一个“消息处理服务”,它在所有服务都收到消息时处理消息的删除(每个服务在处理消息后都会发出一个“消息确认”事件)。

我想我的问题是:我应该使用什么模式来确保我可以为 SQS 中的单个队列拥有多个消费者,同时确保消息也能够可靠地传递和删除。谢谢您的帮助。

4

3 回答 3

70

我认为你做错了。

在我看来,您正在使用同一个队列来做多种不同的事情。您最好将单个队列用于单个目的。

而不是将事件放入'registration-new'队列,然后让两个不同的服务轮询该队列,并且两者都需要读取该消息并且都对其执行不同的操作(然后需要一个应该删除的第三个进程)其他 2 个处理后的消息)。

一个队列应该用于一个目的。

  • 创建一个 'index-user-search' 队列和一个 'send to mixpanels' 队列,以便搜索服务从搜索队列中读取,索引用户并立即删除消息。

  • mixpanel-service 从 mix-panels 队列中读取,处理
    消息并删除消息。

注册服务,而不是将“registration-new”发送到单个队列,现在将其发送到两个队列。

为了更进一步,在这里添加 SNS 并让注册服务向“registration-new”主题(不是队列)发出 SNS 消息,然后将我上面提到的两个队列订阅到该主题“扇出”模式。

https://aws.amazon.com/blogs/aws/queues-and-notifications-now-best-friends/

两个队列都会收到消息,但您只需将其加载到 SNS 中一次 - 如果未来第三个不相关的服务也需要处理“注册新”事件,您可以创建另一个队列并将其订阅到主题 - 它可以在不依赖或不知道其他服务在做什么的情况下运行——这就是目标。

于 2015-05-18T08:25:48.720 回答
6

队列的多个消费者的主要用例是向外扩展

允许多个消费者的机制是Visibility Timeout,它给消费者时间来处理和删除消息,而不会被另一个消费者同时消费。

为了解决标准队列的“至少一次交付”属性,消费服务应该是幂等的。如果这不可行,一种可能的解决方案是使用FIFO 队列,但这种模式的消息传递率有限,并且与 SNS 订阅不兼容

于 2020-02-11T15:44:06.520 回答
1

他们甚至有一个关于如何使用组合 SNS+SQS 创建扇出场景的教程。

https://aws.amazon.com/getting-started/tutorials/send-fanout-event-notifications/

太糟糕了,它不支持 FIFO 队列,因此您必须小心处理乱序消息。

如果他们有一个一致的散列解决方案来让多个竞争消费者同时尊重消息顺序,那就太好了。

于 2019-12-14T19:11:51.710 回答