将 Amazon SQS 与多个消费者一起使用
Using Amazon SQS with multiple consumers
我有一个基于服务的应用程序,它使用具有多个队列和多个消费者的 Amazon SQS。我这样做是为了实现基于事件的架构并解耦所有服务,其中不同的服务对其他系统状态的变化做出反应。例如:
- 注册服务:
- 当新用户注册时发出事件 'registration-new'。
- 用户服务:
- 更新用户时发出事件 'user-updated'。
- 搜索服务:
- 从队列中读取 'registration-new' 并在搜索中索引用户。
- 从队列中读取 'user-updated' 并更新搜索中的用户。
- 指标服务:
- 从 'registration-new' 队列中读取并发送到 Mixpanel。
- 从队列 'user-updated' 中读取并发送到 Mixpanel。
我有很多问题:
- 轮询时,一条消息可能会收到多次。我可以将很多系统设计成幂等的,但是对于某些服务(例如指标服务)来说,这会困难得多。
- 需要从SQS 的队列中手动删除一条消息。我想过实现一个 "message-handling-service" 来处理消息的删除,当所有服务都收到消息时(每个服务都会在处理消息后发出一个 'message-acknowledged' 事件)。
我想我的问题是:我应该使用什么模式来确保 SQS 中的单个队列可以有多个消费者,同时确保消息也能可靠地传递和删除。感谢您的帮助。
我认为你做错了。
在我看来,您好像在使用同一个队列来做多个不同的事情。您最好为单一目的使用单个队列。
而不是将事件放入 'registration-new' 队列,然后让两个不同的服务轮询该队列,并且两者都需要读取该消息并对其执行不同的操作(然后需要第三个进程应该在其他 2 个处理完后删除该消息)。
一个队列应该用于一个目的。
创建一个'index-user-search'队列和一个'send to mixpanels'队列,
所以搜索服务从搜索队列中读取,索引用户
并立即删除该消息。
混合面板服务从混合面板队列中读取,处理
消息并删除消息。
注册服务不再将 'registration-new' 发送到单个队列,而是将其发送到两个队列。
为了更进一步,在此处将 SNS 添加到组合中,让注册服务向 'registration-new' 主题(不是队列)发送 SNS 消息,然后订阅我上面提到的两个队列, 以 'fan-out' 模式指向该主题。
https://aws.amazon.com/blogs/aws/queues-and-notifications-now-best-friends/
两个队列都会收到消息,但您只将其加载到 SNS 一次 - 如果在路上第三个不相关的服务也需要处理 'registration-new' 事件,您创建另一个队列并将其订阅到主题同样 - 它可以 运行 不依赖或不知道其他服务在做什么 - 这就是目标。
他们甚至有关于如何使用组合 SNS+SQS 创建扇出场景的教程。
https://aws.amazon.com/getting-started/tutorials/send-fanout-event-notifications/
太糟糕了,它不支持 FIFO 队列,因此您必须小心处理乱序消息。
如果他们有一个一致的哈希解决方案来拥有多个竞争消费者,同时尊重消息顺序,那就太好了。
一个队列的多个消费者的主要用例是scaling-out。
允许多个消费者的机制是 Visibility Timeout,它让消费者有时间处理和删除消息,而不会被另一个消费者同时消费。
要解决标准队列的 "At-Least-Once Delivery" 属性,
消费服务应该是idemptotent。
如果那不可能,一种可能的解决方案是使用 FIFO queues, but this mode has a limited message delivery rate and is not compatible with SNS subscription.
我有一个基于服务的应用程序,它使用具有多个队列和多个消费者的 Amazon SQS。我这样做是为了实现基于事件的架构并解耦所有服务,其中不同的服务对其他系统状态的变化做出反应。例如:
- 注册服务:
- 当新用户注册时发出事件 'registration-new'。
- 用户服务:
- 更新用户时发出事件 'user-updated'。
- 搜索服务:
- 从队列中读取 'registration-new' 并在搜索中索引用户。
- 从队列中读取 'user-updated' 并更新搜索中的用户。
- 指标服务:
- 从 'registration-new' 队列中读取并发送到 Mixpanel。
- 从队列 'user-updated' 中读取并发送到 Mixpanel。
我有很多问题:
- 轮询时,一条消息可能会收到多次。我可以将很多系统设计成幂等的,但是对于某些服务(例如指标服务)来说,这会困难得多。
- 需要从SQS 的队列中手动删除一条消息。我想过实现一个 "message-handling-service" 来处理消息的删除,当所有服务都收到消息时(每个服务都会在处理消息后发出一个 'message-acknowledged' 事件)。
我想我的问题是:我应该使用什么模式来确保 SQS 中的单个队列可以有多个消费者,同时确保消息也能可靠地传递和删除。感谢您的帮助。
我认为你做错了。
在我看来,您好像在使用同一个队列来做多个不同的事情。您最好为单一目的使用单个队列。
而不是将事件放入 'registration-new' 队列,然后让两个不同的服务轮询该队列,并且两者都需要读取该消息并对其执行不同的操作(然后需要第三个进程应该在其他 2 个处理完后删除该消息)。
一个队列应该用于一个目的。
创建一个'index-user-search'队列和一个'send to mixpanels'队列, 所以搜索服务从搜索队列中读取,索引用户 并立即删除该消息。
混合面板服务从混合面板队列中读取,处理
消息并删除消息。
注册服务不再将 'registration-new' 发送到单个队列,而是将其发送到两个队列。
为了更进一步,在此处将 SNS 添加到组合中,让注册服务向 'registration-new' 主题(不是队列)发送 SNS 消息,然后订阅我上面提到的两个队列, 以 'fan-out' 模式指向该主题。
https://aws.amazon.com/blogs/aws/queues-and-notifications-now-best-friends/
两个队列都会收到消息,但您只将其加载到 SNS 一次 - 如果在路上第三个不相关的服务也需要处理 'registration-new' 事件,您创建另一个队列并将其订阅到主题同样 - 它可以 运行 不依赖或不知道其他服务在做什么 - 这就是目标。
他们甚至有关于如何使用组合 SNS+SQS 创建扇出场景的教程。
https://aws.amazon.com/getting-started/tutorials/send-fanout-event-notifications/
太糟糕了,它不支持 FIFO 队列,因此您必须小心处理乱序消息。
如果他们有一个一致的哈希解决方案来拥有多个竞争消费者,同时尊重消息顺序,那就太好了。
一个队列的多个消费者的主要用例是scaling-out。
允许多个消费者的机制是 Visibility Timeout,它让消费者有时间处理和删除消息,而不会被另一个消费者同时消费。
要解决标准队列的 "At-Least-Once Delivery" 属性, 消费服务应该是idemptotent。 如果那不可能,一种可能的解决方案是使用 FIFO queues, but this mode has a limited message delivery rate and is not compatible with SNS subscription.