Rabbitmq 队列公平性和消息传递服务器

Rabbitmq 队列公平性和消息传递服务器,rabbitmq,jms,message-queue,messaging,Rabbitmq,Jms,Message Queue,Messaging,我希望解决一个问题,我与先进先出性质的消息服务器和队列。在某些情况下,我希望将队列中的消息分发给消费者池,而不是按照消息传递顺序。理想情况下,这将防止用户占用系统中的共享资源。以这个过度简化的场景为例: 应用程序中有一个功能,用户可以在其中清空垃圾桶 此事件为垃圾桶中的每个项目发送删除消息 此队列的使用者调用具有速率限制API的web服务 考虑到每个用户的垃圾桶中都有大量的消息,我们有哪些选项可以允许在不考虑排队时间的情况下并发处理每个垃圾桶?在我看来,有几个显而易见的解决方案: 为每个用

我希望解决一个问题,我与先进先出性质的消息服务器和队列。在某些情况下,我希望将队列中的消息分发给消费者池,而不是按照消息传递顺序。理想情况下,这将防止用户占用系统中的共享资源。以这个过度简化的场景为例:

  • 应用程序中有一个功能,用户可以在其中清空垃圾桶
  • 此事件为垃圾桶中的每个项目发送删除消息
  • 此队列的使用者调用具有速率限制API的web服务
考虑到每个用户的垃圾桶中都有大量的消息,我们有哪些选项可以允许在不考虑排队时间的情况下并发处理每个垃圾桶?在我看来,有几个显而易见的解决方案:

  • 为每个用户创建单独的队列和消费者池
  • 将消息传递从单个队列随机分配到单个使用者池
在我们的例子中,创建一个单独的队列并为每个用户管理消费者实际上是不实际的。这是可以做到的,但如果第二种选择合理的话,我真的更喜欢它。我们正在使用RabbitMQ,但如果有更适合此任务的技术,则不一定要与之绑定

我很乐意使用Rabbit的消息优先级来帮助随机传递。通过随机为消息分配1到10之间的优先级,这将有助于分发消息。此方法的问题是,如果队列从未完全清空,则具有最低优先级的消息可能永远卡在队列中。我想我可以在邮件上使用TTL,然后以升级的优先级重新排队,但我在以下列表中注意到了这一点:

应该过期的邮件仍将仅从邮件头过期 排队。这意味着与普通队列不同,即使是每个队列 TTL会导致过期的低优先级消息被延迟 未过期的更高优先级的。这些信息永远不会被发现 已传递,但它们将显示在队列统计信息中


我担心我会用这种方法陷入困境。我想知道其他人是如何解决这个问题的。任何关于创造性路由、消息传递模式或任何替代解决方案的反馈都将被告知。

一个解决方案可以是插入一个新的解决方案。原理在该链接的diag中概述。在您的情况下,类似于:

  • 应用程序会像最初一样将其删除消息发送到删除队列中
  • 重新排序器(您编写的新组件)插入原始发布者和原始使用者之间。它:

    • 将消息从删除队列拉入内存
    • 按用户将它们放入(内存中)队列
    • 将它们重新发布到一个新队列(例如FairPriorityDeleteQueue),绕过robinning,将来自不同原始用户的任何消息完全交错
    • 将其重新发布速率限制在FairPriorityDeleteQueue中,使FairPriorityDeleteQueue的长度(可通过定期轮询rabbitmq管理api获得)永远不会超过您选择的某个整数N,或限制为与使用者使用的速率受限删除api相关的某个速率
    • 不确认从原始删除队列中提取的任何消息,直到将其重新发布到FairPriorityDeleteQueue(这样您就不会丢失消息)
  • 原始使用者订阅FairPriorityDeleteQueue


    • 您将这些消费者的预回迁次数设置得相当低(我认为在这种情况下不需要重新排序。如果您需要确保按特定顺序删除项目,可能需要重新排序。但只有在您大致同时发送多条消息并且需要确保消费者端的顺序时,这一点才起作用

      出于您提到的原因,您还应该避免出现超时情况。超时是为了告诉RabbitMQ消息不需要处理,或者需要将消息路由到死信队列,以便其他代码可以处理消息。虽然您可以使超时工作,但我认为这不是一个好的选择

      优先级可能会解决部分问题,但可能会导致无法处理文件的情况。如果队列中的某个位置有优先级为1的消息,而您一直将优先级为2、3、5、10等放入队列,则可能无法处理优先级为1的消息。如您所述,超时无法解决此问题

      就我个人而言,我建议采用另一种方法:针对单个文件连续发送删除请求

      也就是说,发送一条消息以删除一个文件。等待响应表明已完成。然后发送下一条消息以删除下一个文件

      以下是我认为这会起作用的原因,以及如何管理它:

      长时间运行的工作流,单文件删除请求 在这个场景中,我建议使用“传奇”(aka)的思想采取多步骤的方法来解决这个问题

      当用户请求删除其垃圾桶时,您通过rabbitmq向可处理删除过程的服务发送一条消息。该服务为该用户的垃圾桶创建一个saga实例

      这个故事收集了垃圾桶中需要删除的所有文件的列表,然后开始发送删除单个文件的请求,一次一个

      每次请求删除一个文件时,saga都会等待响应说该文件已被删除

      当saga收到消息说上一个文件已被删除时,它会发出下一个删除下一个文件的请求

      一旦所有的文件都被删除了,传奇故事就会更新自身和系统的任何其他部分,说垃圾桶是空的

      处理多个用户 当你有一个用户请求删除时,事情会很快发生 u1 = User 1 Trashcan Delete Request |u1|u1|u1|u1|u1|u1|u1|u1|u1|u1done| u1 = User 1 Trashcan Delete Request u2 = User 2 Trashcan Delete Request |u1|u2|u1|u1|u2|u2|u1|u2|u1|u2|u2|u1|u1|u1|u2|u2|u1|u2|u1|u1done|u2|u2done|