2009年3月15日星期日

WLS_042:常见故障之十:JMS Queue中的消息被“重复消费”问题

正常情况下,Sender把消息发送到Queue以后,Receiver成功读取之后,Queue中的消息应该不存在了。
但有时,我们会发现消息依然在Queue中存在,这是怎么回事呢?
既然Sender已经把消息发送到Queue中了,表明事务已经成功完成了。因此,问题应该出现在Receiver代码中。
在Receiver代码中,我们重点看init()和onMessage()方法:

1.init()
public void init(Context ctx, String queueName)
throws NamingException, JMSException
{
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(queueName);
qreceiver = qsession.createReceiver(queue);
qreceiver.setMessageListener(this);
qcon.start();
}

注意创建Session时使用的参数是Session.CLIENT_ACKNOWLEDGE,这说明需要明确告诉JMS消息是否接收成功,否则Queue中的消息将一直存在。

2.onMessage()
成功获取消息后,增加语句msg.acknowledge();,表明消息是否接收成功,事务成功完成。

public void onMessage(Message msg)
{
try {
String msgText;
if (msg instanceof TextMessage) {
msgText = ((TextMessage)msg).getText();
} else {
msgText = msg.toString();
}

msg.acknowledge();

} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

3. 如果创建Session时使用的参数是Session.AUTO_ACKNOWLEDGE
该参数的意义是只要onMessage方法成功返回(没有抛出异常),就认为消息成功收到了。此时,不需要在onMessage方法中增加语句msg.acknowledge();。

没有评论: