2016-10-03 82 views
0

我遇到了处理与特定源相关的事件的情况。每个源都有一个密钥或ID,我可以用它作为散列。来自每个来源的事件必须按顺序处理,但是来自不同来源的事件可以并行化,以实现水平可伸缩性。将有数百个源密钥。使用一致的哈希交换绑定的过期队列上的死信刻录消息

我打算在将消息提交给RabbitMQ时将密钥设置为路由密钥的一部分,然后使用consistent-hash-exchange,以便将来自同一源的事件路由到同一队列。当时我正在考虑使用TTL动态绑定来自消费者的私有队列(以便在消费者关闭的情况下优雅地删除它们)。一开始我只有2或3个消费者用于冗余,但是如果我想通过增加消息数量来扩大规模,我可以启动另一个消费者。

我的问题是如果消费者关闭并且队列中有消息会发生什么?理想情况下,我希望将队列中的消息重新路由回交换机,由consistent-hash-exchange将它们路由到不同的队列(因为原始队列将不再存在)。

关于dead lettering的RabbitMQ文档没有明确提及消费者队列上的TTL场景,或者是在队列被删除时会发生什么情况。

我的方法有道理吗?如何在保留特定路由密钥的排序的同时实现消费者的容错功能?

注:我知道甚至有一个更微妙的竞争条件,如果在路由死信字母邮件的过程中到达交换新邮件到达最初路由到过期队列,现在将被路由到不同的消费者,因此在该特定情况下订单将被打破。

回答

0

这里有更多的问题需要回答,我会尽量按照相同的顺序进行。

My question is what happens if a consumer is down and there are messages in its queue?
在上下文之外(问题的其余部分) - 消息会保留在队列中,直到它们被确认或TTL过期。

The RabbitMQ documentation about dead lettering doesn't explicitly mention the scenario of TTL on consumer queues, or what happens when the queue gets deleted.
确实...The TTL for the message expires...,所以基本上如果消息没有给出TTL内获得确认,得到它的到DLX。对于队列TTL,check this link - 它基本上是队列的“到期时间”。此外,如果队列被删除,则消息消失(当然,当然不考虑任何镜像)。

现在为“有意义”的一部分。对于来自不同来源的消息,我认为很清楚 - 尽可能多地进行并行处理,就是这样。那里没有碰撞(通常很少)。

How can I achieve the consumer fault-tolerance I am looking for while retaining the ordering by a specific routing key?
对于顺序处理,基本上你只需要一个消费者来完成一个源代码。现在为了监视这个消费者,可能会添加一个看门狗,如果它崩溃,则重新启动;或者如果挂起,则重新启动它。也许使用get而不是consume(amqp)方法也是有意义的。我不能真正推荐或不推荐这种方法,因为(至少对我而言)它是相当具体的用例(性能,多久出现一条新消息等),但我认为这样做更容易实现“更同步”的行为。

当然,如果你真的想要保留序列的原始顺序(现在称为冗余),你应该尝试避免DLX消息(更高的TTL等) :))

+0

感谢您的回复。关于频率,在高峰时间消息数量相当多。我可能会过度设计这一点。如果消费者消失,我所寻找的是一种自动重新路由消息。我想我可以让消息TTL比队列TTL更短,这样如果消费者断开连接,消息先是DLXed,然后队列TTL过期并被删除。是的,仍然存在订购DLX消息和竞争条件与来自相同源密钥的新消息的问题。 – jbx

+0

不客气。正如我所说,我会为消费者解决这个“消费方面的问题”。你想要消费者为了继续处理顺序,但也希望它运行:) – cantSleepNow

+0

是的,我的担心是更多的如果运行消费者的机器死亡,需要超过几分钟才能恢复。公平地说,如果队列具有相对较短的TTL(例如30秒)并且消费者不重新连接,那么将会有潜在的30秒的新消息。我对DLXing的假设不起作用,因为消息可能在队列TTL到期之前的最后一秒进入。或者,我可以在客户端断开连接后立即删除队列,以便只丢失几条消息...不理想丢失消息:( – jbx