连接到 ActiveMQ Artemis 队列的单个消费者中的消息顺序问题

Message order issue in single consumer connected to ActiveMQ Artemis queue

接收单个队列消费者和多个生产者时是否可能出现消息顺序问题? producer12021-06-27 02:57:44.513 上发布消息 m1,在同一队列 worker_consumer_queueproducer22021-06-27 02:57:44.514 上发布消息 m2。连接到配置为单个消费者的队列的客户端代码应该按顺序 m1 先接收消息然后 m2 正确吗?有时消息接收顺序错误。版本是 ActiveMQ Artemis 2.17.0。 尽管我提到了多个生产者,消息使用 属性 blockOnDurableSend=false.

从同一个线程一个接一个地发布

我在每次发布消息时创建并关闭生产者。在同一个 JVM 上,我的假设是队列中发布消息的顺序,来自同一线程或来自不同线程,即使是异步的。时间戳是 getJMSTimestamp()。异步发布还维护任何内部队列有顺序吗?

好吧,因为它接缝它不是 Artemis 中的错误,当涉及到毫秒差异时,它更像是网络延迟或类似的东西。

因此,为了解决这个问题,我想到了这个想法,您可以创建一个算法,在该算法中,收到的消息将等待 ~100 毫秒才能真正处理(无论您想对此消息做什么)并检查是否有是您的应用程序之后收到但之前发送的另一条消息。所以基本上有你自己的延迟接收队列。

如果之前有消息,您可以简单地在您的个人算法中将其上移。您还可以考虑拒绝返回总线的第一条消息,这取决于您对队列和主题的设置,它可以在之后再次接收它。

如果有多个生产者,则无法保证消息会按顺序处理。

多生产者,ActiveMQ Artemis 和一个消费者是一个分布式系统,没有全局时钟是分布式系统的一个显着特征。

即使生产者和 ActiveMQ Artemis 在同一台机器上并使用相同的时钟,ActiveMQ Artemis 也无法按照生产者创建和发送消息的相同顺序接收消息。因为创建消息的时间和发送消息的时间包括可变时间延迟。

最简单的解决方案是信任 ActiveMQ Artemis 收到的消息的顺序,添加带有 interceptor or enabling the ingress timestamp, see ARTEMIS-2919 的时间戳以获得更多详细信息。

如果最简单的解决方案行不通,分布式解决方案是实现分布式系统总排序算法lamport timestamps

如果您使用 blockOnDurableSend=false,您基本上是在说您并不严格关心订单,甚至根本不关心消息是否到达代理。使用 blockOnDurableSend=false 基本上意味着“即发即弃”。

此外,JMSTimetamp 而不是 当消息实际发送时如 javax.jms.Message JavaDoc:

中所述

The JMSTimestamp header field contains the time a message was handed off to a provider to be sent. It is not the time the message was actually transmitted, because the actual send may occur later due to transactions or other client-side queueing of messages.