我有一个使用 ActiveMQ 客户端的 .NET 服务。我已经实现了一个带有事务连接的 MessageListener 来使用消息。
有时,我会以不同的顺序将消息放入队列中。
使用 MessageListner 有错吗?有没有办法保留消息顺序?
仅供参考:有一个生产者将消息放入队列,一个消费者将消息从队列中拉出。
你不应该做任何事情来维持秩序;这是消息队列为您做的事情之一。我认为,如果您有一个消费者正在侦听队列,并且它正在无序地处理消息,那么您要么发现了错误,要么消息没有按照您认为的顺序排队。
此外,ActiveMQ FAQ中的这个问题可能会有所帮助。
编辑:通过阅读对duffymo 的回答的评论,看起来你有点过度设计了。一般来说,像 ActiveMQ、MQ Series、joram 等这样的消息队列有两个特点:它们以与入队相同的顺序传递消息,并且它们保证消息传递。发送单独的 ACK 消息是多余的;这有点像提交数据库事务,然后查询相同的信息以再次检查数据库是否实际存储了它。
话虽如此,您的服务器是多线程的吗?如果是这样,它可能会在将 ACK 排入队列之前将响应排入队列。
更多信息:我调用的服务器是第三方服务器,我无法控制它发送的消息。我确实知道,基于它们以正确顺序放置的消息 ID。此外,在该系统中,ACK 和 Acknowledge 之间存在差异。当我的原始消息放入“出站”队列时收到 ACK。然后,我监视“入站”队列以获取响应。我通常会得到一个“确认”,然后是“通过”或“失败”。这些消息的相关 ID 是来自 ACK 的消息 ID。
我最初使用消息侦听器并响应 OnMessge 事件。在意识到使用这种方法后,我放弃了这种方法,消息是异步传递的,因此没有特定的顺序。因此,我将代码更改为使用计时器 (System.Threading.Timer) 进行轮询来调用 consumer.Receive() 并一次获取一条消息。这按我想要的方式工作。
我在服务启动时打开消费者一次,并不断轮询消息。
为什么消息顺序很重要?MessageListener 不必关心。
如果您需要关联 ID 来将响应与特定请求相匹配,那就另当别论了。你是这个意思吗?
杰森刚才所说的一切。还有一些需要注意的事情。您让消费者对大量消息保持开放,对吗?您不是为几条消息创建消费者然后关闭它吗?只有关闭消费者才会导致与消费者关联的消息被放回可能破坏顺序的队列中。
它与回滚有关吗?(您是否回滚任何交易?)。
最后,您始终可以通过使用Resequencer为您重新排序来确保订单。