【问题标题】:AMQP: acknowledgement and prefetchingAMQP:确认和预取
【发布时间】:2014-03-06 07:50:45
【问题描述】:

我尝试了解 AMQP 协议的某些方面。目前我有 RabbitMQ 项目并使用 python pika 库。所以问题是关于确认和消息预取。

  1. 假设我们有一个只有消费者的队列(确保该队列被声明为独占)。那么我是否理解正确:无论我是否使用 ack 标志消费?无论如何,我不应该能够同时处理多条消息,并且没有其他消费者可以接收一些其他仍在排队的消息。最好不要开启确认,因为这可能会减少 AMQP 服务器负载。

  2. 如果没有确认,预取计数没有任何意义。对吗?

  3. 我不确定预取是如何工作的。我对新消息进行了回调,并在其 finally 声明中确认或拒绝了该消息。这是唯一的功能,无论预取计数有多大 - 无论如何,在当前消息完成之前不会处理另一条消息。那么为什么我需要改变 prefetch_count 的值呢?

提前致谢。

【问题讨论】:

    标签: python rabbitmq amqp pika


    【解决方案1】:

    在未设置autoack 标志的情况下,如果您的应用程序在消息处理期间失败,所有收到的消息都将丢失。 If such situation is quite rare and message lose is appropriate option in your application (for example, but no limited to, logs processing) you may turn autoack off.

    是的,取消设置 autoack 需要更简单的代理逻辑,因此它使用的资源更少。

    对于prefetch count(和prefetch size),这些选项告诉代理预先发送给客户端的有效负载可能有多大可能是单个消息。通常它用于节省网络操作等待新消息的时间。当prefetch size 使用的客户端将收到一条或多条消息,其总大小等于或小于预设的 pretch 大小(和/或计数,后者更小)。

    prefetch countprefetch size 规则都适用。当其中一个设置为零(未设置)时,它将不会被应用。

    最重要的是,预取定义了在客户端未确认的更多消息之前发送消息的行为

    结合这两个设置会产生这样的结果:

    预取消息数限制并提前发送消息:

    条件:

    • 队列:N 条消息 x 1kb
    • 预取prefetch-size=5kb, prefetch-count=4
    • 自动确认off

    工作流程:

    • Broker 向客户端发送 4 条消息(受prefetch-count=4 限制)。 4 条消息将被标记为未确认并从队列中移出(因此它们不会被传递给其他客户端)。
    • 客户端确认 1 消息。
    • 代理有 -1 条消息未确认(删除该消息)并向客户端发送 1 条消息(+1 条未确认,-1 来自队列,而客户端已经有 3 条消息未确认)。
    • 客户端确认其余 3 条消息 + 新发送的一条。
    • 代理有 -4 条消息未确认并再次发送 4 条消息,+4 未确认,-4 来自队列。
    • 客户端确认 1 条消息并失败。
    • Broker 将 -1 未确认,然后将其余未确认移回队列,因此 -3 未确认和 +3 排队,因此它们可能会再次传递给此客户端或其他客户端。

    大消息预取:

    条件:

    • 队列:1 条消息 x 5Kb,N 条消息 x 1kb
    • 预取prefetch-size=5kb, prefetch-count=2
    • 自动确认off

    工作流程:

    • Broker 向客户端发送 1 条消息(受 prefetch-size=5kb 限制),该消息被标记为 un-aked。
    • 客户端确认 1 消息。
    • Broker 有 -1 条消息未确认,再次发送 2 条消息(受 prefetch-count=2 限制,请注意,只有第一条消息为 5kb,其余为 1kb)并将这些消息标记为未确认。
    • 客户端确认 1 条消息并失败。
    • Broker 会将已确认的消息移出消息队列,其余未确认的消息将再次移到它们所属的队列中,因此它们可能会再次传递给此客户端或其他客户端。

    自动确认:

    条件:

    • 队列:N 条消息 x 1kb
    • 预取prefetch-size=5kb, prefetch-count=10
    • 自动确认on

    工作流程:

    • 虽然prefetch-sizeprefetch-countno-ack 设置为true 时被忽略(这就是在RabbitMQ 和AMQP 文档中调用自动确认功能的方式),但消息将被一一发送到客户端并被删除发送成功后从队列中。

    注意,AMQP 具有异步架构,因此在某些情况下,两个客户端可以同时接收一条消息。此外,未确认的消息可能会返回给同一个客户端(特别是如果您有单个客户端)。

    另外,请查看prefetch-sizeprefetch-count 官方文档并尝试使用这些选项。

    P.S.:autoack 基本上是no-ack AMQP 标志设置为true

    【讨论】:

    • 很好的答案,谢谢你的例子!所以我理解正确吗:虽然客户端不能同时处理来自队列的多于 1 条消息,但它可以在某种缓存中 prefetch 一些消息(受数量和/或大小限制)以便快速访问它们(不等待他们从服务器)?似乎它是由 AMQP 库在内部实现的,并且对用户是透明的,所以我以与没有它相同的方式进行预取。
    • 在“没有自动确认”的情况下,代理如何知道消费者处理了多少?在您的示例中,您提到处理了 3 条消息,然后代理又发送了两条。你能再解释一下吗?
    • @AkashJain,我的回答中有多个错误,stackoverflow.com/posts/21662129/revisions,现在应该修复。给您带来的不便,我们深表歉意。
    • @Serge 客户端可以“同时”处理许多消息 - 即。与线程。这需要更多的协调和单独的消息跟踪,但完全有可能。唯一的限制是客户端从队列前面读取消息。从那里直到客户端 ACK/NACK/DC,是客户端的责任。
    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多