Jms 如何从Websphere MQ读取大量消息

Jms 如何从Websphere MQ读取大量消息,jms,ibm-mq,messaging,mq,Jms,Ibm Mq,Messaging,Mq,我希望按顺序分组从WebSphereMQ读取10000条消息,我使用下面的代码来执行相同的操作,但读取所有消息需要很长时间。甚至我也尝试使用多线程的概念,但有时两个线程使用相同的组和竞争条件。下面是代码片段。 我尝试使用3个线程从MQ顺序读取10000条消息,但我的两个线程同时访问同一个组。如何避免这种情况?按顺序阅读大量信息的最佳方式是什么。?我的要求是我想按顺序阅读10000条信息。请帮忙 MQConnectionFactory factory = new MQConnectionFacto

我希望按顺序分组从WebSphereMQ读取10000条消息,我使用下面的代码来执行相同的操作,但读取所有消息需要很长时间。甚至我也尝试使用多线程的概念,但有时两个线程使用相同的组和竞争条件。下面是代码片段。 我尝试使用3个线程从MQ顺序读取10000条消息,但我的两个线程同时访问同一个组。如何避免这种情况?按顺序阅读大量信息的最佳方式是什么。?我的要求是我想按顺序阅读10000条信息。请帮忙

MQConnectionFactory factory = new MQConnectionFactory();
factory.setQueueManager("QM_host")
MQQueue destination = new MQQueue("default");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);

MessageConsumer lastMessageConsumer = 
    session.createConsumer(destination, "JMS_IBM_Last_Msg_In_Group=TRUE");
TextMessage lastMessage = (TextMessage) lastMessageConsumer.receiveNoWait();
lastMessageConsumer.close();

if (lastMessage != null) {

    int groupSize = lastMessage.getIntProperty("JMSXGroupSeq");
    String groupId = lastMessage.getStringProperty("JMSXGroupID");

    boolean failed = false;

    for (int i = 1; (i < groupSize) && !failed; i++) {

        MessageConsumer consumer = session.createConsumer(destination,
            "JMSXGroupID='" + groupId + "'AND JMSXGroupSeq=" + i);
        TextMessage message = (TextMessage)consumer.receiveNoWait();

        if (message != null) {
            System.out.println(message.getText());
        } else {
            failed = true;
        }

        consumer.close();

    }

    if (failed) {
        session.rollback();
    } else {
        System.out.println(lastMessage.getText());
        session.commit();
    }

}

connection.close();
MQConnectionFactory工厂=新的MQConnectionFactory();
factory.setQueueManager(“QM_主机”)
MQQueue destination=新MQQueue(“默认”);
Connection=factory.createConnection();
connection.start();
Session Session=connection.createSession(true,Session.AUTO_-ACKNOWLEDGE);
MessageConsumer lastMessageConsumer=
createConsumer(目标,“JMS\u IBM\u Last\u Msg\u In\u Group=TRUE”);
TextMessage lastMessage=(TextMessage)lastMessageConsumer.receiveNoWait();
lastMessageConsumer.close();
if(lastMessage!=null){
int groupSize=lastMessage.getIntProperty(“JMSXGroupSeq”);
String groupId=lastMessage.getStringProperty(“JMSXGroupID”);
布尔失败=错误;
对于(int i=1;(i
我认为更好的方法是在应用程序中有一个协调线程,它将侦听组的最后消息,并为每个组启动一个新线程,以获取属于分配给该线程的组的消息。(这将符合比赛条件。)


在获取属于某个组的消息的线程中,您不需要使用for循环来分别获取每个消息,而是应该获取属于该组的任何消息,同时维护一个组计数器并缓冲无序消息。只要您仅在接收和处理组的所有消息后提交会话,这将是安全的。(这将产生更高的性能,因为每个组将由一个单独的线程处理,并且该线程将只访问MQ中的每条消息一次。)

请参阅IBM关于的文档。如果页面移动或更改,我将引用最相关的部分。为了保证顺序处理,必须满足以下条件:

  • 所有put请求都是从同一个应用程序执行的
  • 所有put请求要么来自同一个工作单元,要么所有put请求都是在一个工作单元之外发出的
  • 所有消息都具有相同的优先级
  • 所有消息都具有相同的持久性
  • 对于远程队列,配置为从发出put请求的应用程序到其应用程序只能有一条路径 队列管理器通过内部通信连接到目标队列 管理器和目标队列
  • 消息不会放入死信队列(例如,如果队列暂时已满)
  • 获取消息的应用程序不会故意更改检索顺序,例如通过指定特定的MsgId 或CorrelId或使用消息优先级
  • 只有一个应用程序正在执行get操作以从目标队列检索消息。如果不止一个 应用程序,这些应用程序必须设计为获得所有 发送应用程序放置的每个序列中的消息
虽然页面没有明确说明这一点,但当他们说“一个应用程序”时,意思是该应用程序的一个线程。如果应用程序具有并发线程,则无法保证处理顺序


此外,按照另一个响应中的建议,在单个工作单元中阅读10000条消息是推荐的保持消息顺序的方法!只有当10000条消息作为一个原子单元必须成功或失败时,才能这样做,这与它们是否按顺序接收无关。如果必须在单个工作单元中处理大量消息,则绝对有必要调整日志文件的大小,很可能还有一些其他参数。保留序列顺序对于任何线程异步消息传输来说都是一种折磨,而不会引入运行时间很长的大量事务。

您可以使用MQ classes for Java(非JMS)做您想做的事情,使用MQ classes for JMS也可以,但这非常棘手

首先从MQ知识中阅读此内容

我将伪代码(来自上面的web页面)转换为Java的MQ类,并将其从浏览更改为破坏性的get

此外,我更喜欢在一个同步点下处理每组消息(假设组的大小合理)

首先,GMO(GetMessageOptions)的“options”字段缺少几个标志,MatchOptions字段需要设置为“MQMO_MATCH_MSG_SEQ_NUMBER”,以便所有线程始终为第一条消息获取组中的第一条消息。i、 e.如上文所述,不要为第一条消息抓取组中的第二条消息

MQGetMessageOptions gmo = new MQGetMessageOptions();
MQMessage rcvMsg = new MQMessage();

/* Get the first message in a group, or a message not in a group */
gmo.Options = CMQC.MQGMO_COMPLETE_MSG | CMQC.MQGMO_LOGICAL_ORDER | CMQC.MQGMO_ALL_MSGS_AVAILABLE | CMQC.MQGMO_WAIT | CMQC.MQGMO_SYNCPOINT;
gmo.MatchOptions = CMQC.MQMO_MATCH_MSG_SEQ_NUMBER;
rcvMsg.messageSequenceNumber = 1;
inQ.get(rcvMsg, gmo);

/* Examine first or only message */
 ...

gmo.Options = CMQC.MQGMO_COMPLETE_MSG | CMQC.MQGMO_LOGICAL_ORDER | CMQC.MQGMO_SYNCPOINT;
do while ((rcvMsg.messageFlags & CMQC.MQMF_MSG_IN_GROUP) == CMQC.MQMF_MSG_IN_GROUP)
{
    rcvMsg.clearMessage();
    inQ.get(rcvMsg, gmo);
   /* Examine each remaining message in the group */
   ...
}
qMgr.commit();