【问题标题】:RabbitMQ and message priorityRabbitMQ 和消息优先级
【发布时间】:2012-05-31 11:38:56
【问题描述】:

RabbitMQ 有消息优先级的概念吗?我有一个问题,一些更重要的消息正在被放慢,因为队列中的消息不太重要。我希望高优先级的优先并排在队列的最前面。

我知道我可以使用两个队列来近似这个,一个“快”队列和一个“慢”队列,但这似乎是一个 hack。

有人知道使用 RabbitMQ 的更好解决方案吗?

【问题讨论】:

  • 很确定队列的重点是它的先进先出,因此优先级的概念消失了。
  • ActiveMQ 等许多技术也有消息优先级的概念。这使队列成为混合 FIFO/优先级队列。

标签: rabbitmq


【解决方案1】:

RabbitMQ / AMQP 肯定有一个消息优先级的概念 - 队列头部的消息优先于它后面的消息,并且该消息优先于它后面的消息,以此类推,无穷无尽。

你能改变那个模型吗?没有! :)

【讨论】:

    【解决方案2】:

    IIRC RabbitMQ 仍然使用 AMQP 协议版本 0.9.1(获取规范 here)。该规范明确提到了消息优先级:

    Messages may have a priority level. A high priority message is sent ahead of lower     priority messages
    waiting in the same message queue. When messages must be discarded in order to maintain a specific
    service quality level the server will first discard low-priority messages.
    

    还有:

    Note that in the presence of multiple readers from a queue, or client transactions, or use of priority fields,
    or use of message selectors, or implementation-specific delivery optimisations the queue MAY NOT
    exhibit true FIFO characteristics.
    

    规范说优先级是必须的,所以我猜 RabbitMQ 应该实现它,但您可能需要查阅它的文档。

    【讨论】:

    • 这个答案是不正确的,直到一周前 RabbitMQ 3.5.0 发布并宣布支持优先级队列 ;-)
    【解决方案3】:

    Rabbit 没有优先级的概念,就像 Brian 简洁地说的那样,前面的那个最先到达那里。 ;-)

    我建议实施一组队列来满足您的特定消息传递需求,并让这些队列模拟您的优先级需求,例如,将它们称为“MyQueueP1”、“MyQueueP2”等等,然后让我们的消费者(s ) 在 P2(等)之前检查 P1,并首先从那里检查服务消息。

    如果你有一个高优先级的消息,你可以通过合适的路由键将它发布到适当的优先级队列中,瞧。

    [更新] 检查这个问题: In a FIFO Qeueing system, what's the best way the to implement priority messaging

    [更新] 根据最近的 RabbitMQ 3.5.0 版,此答案现已过时,应视为仅适用于此版本之前的版本。 https://stackoverflow.com/a/29068288/489888

    【讨论】:

    • 感谢您的回复,我希望避免为此设置多个队列,但看起来这是可行的方法。
    • 来自 [www.rabbitmq.com/api-guide.html] 的一些信息:发布消息部分:这会发送一条消息,传递模式为 2(持久),优先级为 0和内容类型“文本/纯文本”。您可以使用 Builder 类来构建您的消息属性对象,该类可以根据需要提及任意数量的属性,例如: channel.basicPublish(exchangeName, routingKey, new AMQP.BasicProperties.Builder() .contentType("text/plain").deliveryMode (2) .priority(1).userId("bob") .build()), messageBodyBytes);
    • 但是对于“优先级”没有其他解释,它们是什么意思
    • 从 3.5.0 开始 - RabbitMQ 支持优先级队列:rabbitmq.com/priority.html
    • 只有java实现有效吗?我正在努力让它在 C# 中工作。我在这里问了一个问题:http://stackoverflow.com/questions/29221020/rabbitmq-3-5-and-message-priority?lq=1
    【解决方案4】:

    如果它实现了优先级,它就不是一个 MQ。

    MQ 是数据的电子邮件。并且在所有数据传输中保持顺序是至关重要的。如果您切换顺序,删除发生在插入之前,更新会失去顺序。一切正常。

    您可能有一个有效的实现,但也有一些例外,但我发现大多数优先级队列的设计是因为人们对他们的系统架构和其中各部分的交互进行了肤浅的思考。保持事物的顺序几乎总是正确的做法,对于实体内和实体间的交互都是如此。

    为了说明事件 A 的优先级高于事件 B,这两个事件必须始终解耦。当这种情况发生时,人们想知道为什么它们存在于同一个队列结构中。再说一次,如果它与有效载荷相关,那么该有效载荷的计算工作量也会影响系统的性能,因此请尽早做出决定,即在使有效载荷有意义之前。

    【讨论】:

    • 有很多实现消息优先级的消息队列(HornetQ、ActiveMQ...等)以及支持它的大量用例。
    • 实际上,这些只是独立队列概念的逻辑扩展。就管道而言,优先级一词很少有任何真正的含义。它是语义糖。我没有说不要使用它们,我说这是一个需要注意的潜在陷阱。许多程序员认为高优先级意味着更快的执行时间。当他们有一个耦合的进程时,他们认为把它放在低优先级队列中,这就足够了。如果它在大部分时间都有效,它就会被接受并被认为是正确的。然后系统开始莫名其妙地失败,调试起来很糟糕。
    • 切向,但我不明白电子邮件如何保证交付顺序。事实上,电子邮件确实具有(粗略的)传输优先级,通过Precedence: 标头。
    【解决方案5】:

    我们可以通过从https://www.rabbitmq.com/community-plugins.html 安装插件 rabbitmq_priority_queue 使 rabbitmq 成为分布式优先级队列。您必须下载插件 rabbitmq_priority_queue-3.3.x-72d20292.ez 并放入您的 rabbit mq 安装目录的 plugins 文件夹中。重新启动服务器。现在您可以优先将项目插入队列并相应地使用它,已将示例代码粘贴在How to poll the RabbitMQ to get messages in order of priority continuously? 中。

    【讨论】:

      【解决方案6】:

      这个问题的答案已经过时了。从 RabbitMQ 3.5.0 开始,现在有对 AMQP 标准每消息优先级的核心支持。 documentation 包含所有血腥细节,但简而言之:

      • 您需要在创建队列时定义队列的优先级范围;
      • 未设置优先级的消息的优先级为 0;
      • 数字优先级高于队列中设置的最大值的消息将获得队列支持的最高优先级。

      文档中有更多有趣的警告。非常值得一读。

      【讨论】:

      • 你好@Womble,我已经阅读了文档并且在实现它时遇到了一些麻烦。其他文档非常稀少。如果你有任何见解。我的问题是here
      • 似乎不是消息优先级而是消费者优先级,我认为这是不同的概念,不是上述问题的答案。
      • 将其更改为正确答案,因为 RabbitMQ 现在支持优先级队列。
      • 关于 RabbitMq 消息优先级的一件事是消费者很饿。如果您发布大量具有不同优先级的消息,那么它们将倾向于优先级,但这并不能完全保证,因为接收端点会在消息到达时收到消息。另一种方法是启用两个具有不同最大优先级的消费者。具有较高最大值的消费者将处理所有消息,而较低优先级的消费者将仅处理该最大值设置。
      • 如何为消费者设置优先级,谁必须先得到消息还是最后得到消息?
      【解决方案7】:

      是的,RabbitMQ 支持优先级队列。

      要使队列作为优先队列工作,请在声明队列时提供属性x-max-priority

      属性x-max-priority 定义队列支持的最大优先级数。

      在 Java 中,你可以这样做:

      Map<String, Object> props = new HashMap<>();
      props.put("x-max-priority", 10); // max priority number as 10
      channel.queueDeclare(QUEUE_NAME, durable, false, false, props);
      

      要发布特定优先级的消息,请执行以下操作:

      String message = "My message with priority 7";
      AMQP.BasicProperties.Builder basicProps = new AMQP.BasicProperties.Builder();
      basicProps.contentType("text/plain")
                  .priority(7);
      channel.basicPublish("", QUEUE_NAME, basicProps.build(), message.getBytes());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-04
        • 1970-01-01
        • 1970-01-01
        • 2012-09-04
        • 2015-12-23
        • 2015-02-11
        • 2020-04-20
        • 2019-01-19
        相关资源
        最近更新 更多