我有一个C#应用程序,它设置了许多MQ侦听器(多个线程,可能还有多个服务器,每个服务器都有自己的侦听器)。有一些消息将从队列中消失,我将要留在队列中,转到MQ上的下一条消息,但在某些情况下我会想回去重新读取这些消息......
var connectionFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ).CreateConnectionFactory();
connectionFactory.SetStringProperty(XMSC.WMQ_HOST_NAME, origination.Server);
connectionFactory.SetIntProperty(XMSC.WMQ_PORT, int.Parse(origination.Port));
connectionFactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, origination.QueueManager);
connectionFactory.SetStringProperty(XMSC.WMQ_CHANNEL, origination.Channel);
var connection = connectionFactory.CreateConnection(null, null);
_connections.Add(connection);
var session = connection.CreateSession(false, AcknowledgeMode.ClientAcknowledge); //changed to use ClientAcknowledge so that we will leave the message on the MQ until we're sure we're processing it
_sessions.Add(session);
var destination = session.CreateQueue(origination.Queue);
_destinations.Add(destination);
var consumer = session.CreateConsumer(destination);
_consumers.Add(consumer);
Logging.LogDebugMessage(Constants.ListenerStart);
connection.Start();
ThreadPool.QueueUserWorkItem((o) => Receive(forOrigination, consumer));
然后我......
if (OnMQMessageReceived != null)
{
var message = consumer.Receive();
var identifier = string.Empty;
if (message is ITextMessage)
{
//do stuff with the message here
//populates identifier from the message
}
else
{
//do stuff with the message here
//populates identifier from the message
}
if (!string.IsNullOrWhiteSpace(identifier)&& OnMQMessageReceived != null)
{
if( some check to see if we should process the message now)
{
//process message here
message.Acknowledge(); //this really pulls it off of the MQ
//here is where I want to trigger the next read to be from the beginning of the MQ
}
else
{
//We actually want to do nothing here. As in do not do Acknowledge
//This leaves the message on the MQ and we'll pick it up again later
//But we want to move on to the next message in the MQ
}
}
else
{
message.Acknowledge(); //this really pulls it off of the MQ...its useless to us anyways
}
}
else
{
Thread.Sleep(0);
}
ThreadPool.QueueUserWorkItem((o) => Receive(forOrigination, consumer));
所以有几个问题:
如果我不确认它留在MQ上的消息,对吗?
如果消息未被确认,那么默认情况下,当我再次使用相同的侦听器从MQ读取时,它会读取下一个并且不会到达开头,对吧?
如何更改监听器,以便下次读取时从队列开始处开始?
答案 0 :(得分:2)
将消息留在队列中是一种反模式。如果您不想或不能在逻辑的某个点处理消息,那么您有多种选择:
在任何情况下,都不要在队列中留言,并始终前进到下一条消息。这将使应用程序更可预测,更容易推理。您还将避免各种性能问题。如果您的应用程序对邮件传递顺序敏感或可能变得敏感,那么手动确认所选邮件也会与之不一致。
问题:
JMS规范对于未确认消息的行为是模糊的 - 它们可能无序传递,并且在确切地何时传递它们时是未定义的。此外,确认方法调用将确认所有以前收到和未确认的消息 - 可能不是您的想法。
如果您留言,听众可能会立即返回。如果你重新启动它,它当然会重新开始,但是当它坐在那里等待消息时它依赖于实现。
因此,如果你试图让你的设计工作,你可能会在某些情况下得到它的工作,但它不可预测或不可靠。