连接到 ActiveMQ Artemis 队列的单个消费者中的消息顺序问题
Message order issue in single consumer connected to ActiveMQ Artemis queue
接收单个队列消费者和多个生产者时是否可能出现消息顺序问题?
producer1
在 2021-06-27 02:57:44.513
上发布消息 m1
,在同一队列 worker_consumer_queue
上 producer2
在 2021-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.
接收单个队列消费者和多个生产者时是否可能出现消息顺序问题?
producer1
在 2021-06-27 02:57:44.513
上发布消息 m1
,在同一队列 worker_consumer_queue
上 producer2
在 2021-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.