1. 问题描述:
a. 服务端发送500条记录,如果立马启动客户端,客户端接收200条,卡顿之后显示接收数据为200条或者超过200条,而服务端只从队列删除了200条。
b. 如果等待片刻,再启动客户端,可全部接收。
c. 如果在客户端session.commit()之前等待若干长时间,也可全部接收。
2. 可能原因: MQ默认MaxPageSize(maximum number of persistent messages to pagefrom store at a time)为200,分析可能原因是服务端需要时间建立一个page,这个page装满后再建一个page,这些都需要时间;客户端接收太快,很快将200条接收完,而服务器端未来得及建立完下个page,所以客户端以为全部接收完,开始commit,导致服务端只销毁200条记录。
3. 如何解决:适当加大page容量
<policyEntryqueue=">"producerFlowControl="true"memoryLimit="2mb"maxPageSize="1000"/>
参考程序:点对点PTP模式
服务端:
package cn.ac.iscas.zdy.p2p;
import javax.jms.DeliveryMode;
import javax.jms.MapMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class QueueSender {
private static final int SEND_NUM = 1500;
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String DESTINATION = "hoo.mq.queue";
public static void sendMessage(QueueSession session, javax.jms.QueueSender sender) throws Exception {
for (int i = 0; i < SEND_NUM; i++) {
String message = "发送消息第" + (i + 1) + "条";
MapMessage map = session.createMapMessage();
map.setString("text", message);
map.setLong("time", System.currentTimeMillis());
System.out.println(map);
sender.send(map);
//Thread.sleep(1000);
}
}
public static void run() throws Exception {
QueueConnection connection = null;
QueueSession session = null;
try {
QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
connection = factory.createQueueConnection();
connection.start();
session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(DESTINATION);
javax.jms.QueueSender sender = session.createSender(queue);
sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
sendMessage(session, sender);
session.commit();
} catch (Exception e) {
throw e;
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
QueueSender.run();
}
}
客户端:
package cn.ac.iscas.zdy.p2p;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class QueueReceiver {
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String TARGET = "hoo.mq.queue?customer.prefetchSize=400";
public static void run() throws Exception {
QueueConnection connection = null;
QueueSession session = null;
try {
QueueConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,ActiveMQConnection.DEFAULT_PASSWORD,BROKER_URL);
connection = factory.createQueueConnection();
((ActiveMQConnection)connection).setUseAsyncSend(true);
connection.start();
session = connection.createQueueSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(TARGET);
javax.jms.QueueReceiver receiver = session.createReceiver(queue);
receiver.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
if (msg != null) {
MapMessage map = (MapMessage) msg;
try {
System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
Thread.sleep(1000*10);
session.commit();
} catch (Exception e) {
throw e;
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
public static void main(String[] args) throws Exception {
QueueReceiver.run();
}
}