在分布式系统中设计公平消息消耗

时间:2016-01-19 03:01:12

标签: activemq

我们有一个分布式应用程序,可以代表多个客户端工作。现在,当工作到达时,消息被放在一个队列中。这些消息是按FIFO顺序提取的,大部分时间都可以正常工作。

在某些情况下,我们会为单个客户端获取数千条消息,然后占用队列中的前1000个插槽。这意味着在处理这些消息之前,任何其他客户端都不能(或很少)工作 - 这会使较小的客户端匮乏。

我的想法是,在我们引用客户端列表之前,每次在从队列中收到消息之前,我们都会查看消息以查看哪个客户端提交了消息。如果它是针对我们刚刚处理的同一个客户端,我们会将其推回,直到我们为不同的客户端找到消息,或者我们迭代所有客户端并找不到其他工作。

这是一个合理的解决方案吗?这是一个已经解决的问题,如果是这样的话?

我已经看过这个问题(Is "fair queuing" possible with JMS),但我不认为群组是正确的答案,因为我不希望所有消息都发送到单个服务器。我只是希望为其他客户提供一个公平的机会进行处理,而无需排队等待单个客户的其他一千条消息。

目前我们使用ActiveMQ作为消息排队系统。

1 个答案:

答案 0 :(得分:0)

您的提案是合理的,但对于可以在多台计算机上同时处理多条消息的分布式系统,我建议另一种方法:使用一次处理多条消息的线程池,您可以使用一个解决方案包括"溢出队列"。

  • 从主队列中读取时,检查是否已为客户处理超过X条消息(您的公平阈值)。如果是这样,请将消息放入溢出队列而不是处理它。
  • 保留少量线程(Y)来处理该队列,其余用于主队列。
  • Y应该是可配置的,以便在溢出相对于主队列非常大时(或当主队列​​为空时)继续处理。或者,而不是Y线程进行溢出处理,只需将其设为百分比 - 例如90%的消息来自主队列,10%来自溢出。

这导致更公平的处理 - 大多数处理使用主队列(现在只允许"公平"消息通过),并且您的重度用户仍将获得超过X的一些吞吐量(具有溢出处理) 。

不是"最好的"解决方案,但它相当不错,而且实施起来相对简单。

确保在您的队列大小上有一些指标,以查看是否存在大量积压(或空队列),并且理想情况下会自动调整参数,以便在流量较低时为溢出提供更高优先级主队列。