JMS/Active MQ - 代理与消费者重新交付

Posted

技术标签:

【中文标题】JMS/Active MQ - 代理与消费者重新交付【英文标题】:JMS/Active MQ - broker vs consumer redelivery 【发布时间】:2014-10-23 12:44:36 【问题描述】:

据我了解 (http://activemq.apache.org/message-redelivery-and-dlq-handling.html),消费者或经纪人都可以重新交付。 不过我有一些问题:

消费者的重新交付如何在下面进行?消费者是否缓存来自代理的消息并在本地重新传递?如果消费者在两者之间终止会发生什么?这样的消息会丢失吗?我认为只要消费者不承认消息,它就不应该承认。但是在这种情况下,消息在代理上仍然可用吗?

在使用代理与消费者重新交付时是否有任何指导?有什么建议吗?

【问题讨论】:

【参考方案1】:

消费者在本地缓存并重新传递消息给客户端,直到满足重新传递计数,然后自动将消息确认为坏消息(posin ack)。消费者可以根据确认模式控制它是否被标记为重新交付。如果出于某种原因消费者不能或不想处理消息,它也可以将其踢回,如果它关闭会话,它将再次可供消费。

代理将保留消息,直到它从消费者那里得到确认。如果您的消费者设置为 AUTO_ACKNOWLEDGE,那么如果发生未处理的异常或消费者意外结束,您可能会丢失消息。

否则,如果您的消费者正在使用事务或 CLIENT_ACKNOWLEDGE,它将让您控制何时发生。

对于事务,如果消费者在提交之前掉线,它将可供下一个消费者使用,或者在该消费者重新连接时可用。

我一直在 CLIENT_ACKNOWLEDGE 上使用事务,所以我不想肯定地说,如果在消费者关闭之前没有调用 Session.recover(),消息将会丢失。

从消费者的角度来看,这也称为重试逻辑。

关于代理与消费者的重新交付:默认情况下,代理只是不断向消费者提供相同的消息,直到满足重新交付计数。如果您告诉代理在给定的时间后不要重新发送它,那么您的消费者可以处理其他可能能够处理的消息。

何时执行此操作实际上取决于您的应用程序中发生的情况。也许需要将特定消息放入数据库,而该数据库目前不可用,而您想继续处理其他地方/有其他目的的消息?

【讨论】:

这并不完全正确。 ActiveMQ MessageConsumer 确实保存了已在事务中传递的消息的缓存,并将在本地重新传递它们,直到 TX 回滚时设置的重新传递限制。 @TimBish 感谢您的标注。我以为已经编辑了这个。我开始考虑其他事情的反应。 这是否意味着如果我们选择broker redelivery那么消息将不会被缓存在consumer上并且每次都来自broker(从而增加了网络使用率)?另一个问题:是否存在诸如确认超时之类的东西,以便代理或消费者在一段时间后重新传递消息而没有 ACK? 当使用代理重新传递时,它不应被缓存,因为消息可以立即重新发送给任何其他消费者(如果配置为这样做的话)。 在大多数情况下,重新投递很少发生,但从技术上讲,它会增加网络使用率。没有确认超时。代理会将消息标记为已分派给该消费者,直到消费者的会话消失或生成 ack,因此客户端代码将需要确定某些事情是否需要很长时间才能处理。但是,您可以有连接超时

以上是关于JMS/Active MQ - 代理与消费者重新交付的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ学习总结

RabbitMQ必备核心知识

SimpleMessageListenerContainer:消费者引发异常,如果处理支持它可以重新启动处理

mq消息消费

框架篇——Spring整合ActiveMQ(MQ服务端与消费端演示)

奇怪的汉诺塔