当使用 RabbitMQ 作为消息代理时,我有一个场景,多个并发消费者使用 basic.get AMQP 方法从队列中提取消息,并使用显式确认从队列中删除消息。假设以下设置
Q 有消息 M1、M2、M3 并且有消费者 C1、C2 和 C3(每个都有自己的连接和 channel )连接到它。
最佳答案
您的问题确实触及了排队和流程理论的核心,所以我将从这个角度回答(就我的回答而言,RabbitMQ 确实是一个通用的消息代理,因为这适用于任何消息代理)。
How is concurrency handled in the basic.get method? Is the call to basic.get method synchronized to handle concurrent consumers each using its own connection and channel? C1, C2 and C3 issue a basic.get call to receive a message at the same time (assume the server receives all 3 requests simultaneously).
答案 1 : RabbitMQ 旨在成为一个可靠的消息代理。它包含内部流程和控制,以确保相同的消息不会多次传递给不同的消费者。现在,由于测试您描述的场景不切实际,它是否完美运行?谁知道。这就是为什么使用基于消息架构的正确设计的应用程序将使用幂等事务,这样如果多次处理同一个事务,结果将与事务处理一次相同。
外卖 :设计您的应用程序,使这个问题的答案不重要。
C1 requests a message using basic.get and gets M1. When C2 requests for a message, since its using a different connection, does it get M1 again?
答案 2 : 不。根据我之前回答的假设,RabbitMQ 代理一旦传递了相同的消息,就不会返回相同的消息。根据 channel 和队列的设置,消息可能会在传递时自动确认并且永远不会重新传递。其他设置将使消息在处理线程/ channel “死亡”或来自处理线程的否定确认时自动重新排队。这是一项重要的功能,因为如果“毒药”消息可以提供给多个消费者,它可能会反复对您的应用程序造成严重破坏。 外卖 :在设计应用程序时,您可以放心地依赖此假设。
How can consumers pull messages in batches of a predefined size?
答案 : 他们不能,对他们来说也没有意义。在任何排队系统中,基本假设是从单个文件中的队列中删除项目。试图违反这一假设会导致不可预测的行为;此外,单件流通常是最有效的处理方法。但是,在现实世界中,有时需要批量大小 > 1。在这种情况下,将批处理加载到它自己的单个消息中是有意义的,因此这可能需要一个单独的处理线程来从队列中提取消息并将它们批处理在一起,或者最初将它们分批处理。请记住,一旦您有多个消费者,就无法保证按顺序处理单个消息。 外卖 :应尽可能避免批处理,但在无法避免的情况下,您不能假设批处理将包含任何特定顺序的单个消息。
关于rabbitmq - AMQP basic.get 从队列中拉取并发消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27067833/