在 ActiveMQ Artemis 中,队列的重新传递是无序的

Redelivery from queue is unordered in ActiveMQ Artemis

如果 ActiveMQ Artemis 配置为 redelivery-delay > 0 且 JMS 侦听器使用 ctx.rollback()ctx.recover(),则代理将按预期重新传送消息。但是,如果生产者在重新传递期间将消息推送到队列,则接收者将获得无序消息。

例如:

队列:1 -> 消息 1 按预期重新传送

在重新交付阶段推送

队列:2,3 -> 接收者得到 2,3,1

redelivery-delay0 一切正常,但消费者端的重新交付频率太高。我的期望是,在未确认的消息从队列中清除或得到确认之前,应该停止每次向消费者的传递。我们正在使用队列连接单个设备。每个设备都有自己的 I/O 队列,只有一个消费者。 queue 这个词对我来说意味着严格的排序。将此行为设置为可配置的 "strict_redelivery_order" 可能会很好。

您看到的是预期的行为。如果您使用 redelivery-delay > 0,则交货顺序将被破坏。如果您使用 redelivery-delay0,则交货订单不会被破坏。因此,如果您想保持严格的顺序,请使用 redelivery-delay of 0.

如果代理在重新传递延迟期间阻止传递队列中的所有其他消息,这将完全破坏消息吞吐量性能。如果重新传递延迟为 60 秒或 10 分钟怎么办?整个时间队列都会被阻塞。这对于为数百或数千个客户端提供服务的企业消息代理来说是站不住脚的,每个客户端都可能定期触发共享队列上的重新传递。此行为不可配置。

如果即使对于无法立即使用的消息,您也绝对必须保持消息顺序,并且 redelivery-delay0 会导致重新传递过快,那么我会看到一些可能的选择(没有特别说明)顺序):

  • 配置 dead-letter address 并将 max-delivery-attempts 设置为合适的值,以便在几次重新传递后可以从队列中清除有问题的消息。
  • 在您的客户端中实施您自己的延迟。这可能就像捕获任何异常并在调用 ctx.rollback().
  • 之前使用 Thread.sleep() 一样简单