Java IBM MQQueue获取所有消息的最安全方式

Java IBM MQQueue获取所有消息的最安全方式,java,ibm-mq,Java,Ibm Mq,我有一个简单的java程序,可以使用IBM MQ将消息从队列a传输到队列B 我的程序运行良好,但我担心的是丢失消息。我知道。get将从队列A中删除消息。因此,当然,有一段时间我从队列A中获得了一条消息,但我尚未将其放入队列B。如果我的程序在此期间崩溃,消息将丢失 为了解决这个问题,我正在将当前消息写入日志。然后,如果程序崩溃,我们可以手动将消息输入回队列 但是-如果程序因IOException崩溃怎么办?现在,消息已从队列A中消失,尚未放入队列B,并且尚未写入日志 在我看来,我有两个选择: 首先

我有一个简单的java程序,可以使用IBM MQ将消息从队列a传输到队列B

我的程序运行良好,但我担心的是丢失消息。我知道。get将从队列A中删除消息。因此,当然,有一段时间我从队列A中获得了一条消息,但我尚未将其放入队列B。如果我的程序在此期间崩溃,消息将丢失

为了解决这个问题,我正在将当前消息写入日志。然后,如果程序崩溃,我们可以手动将消息输入回队列

但是-如果程序因IOException崩溃怎么办?现在,消息已从队列A中消失,尚未放入队列B,并且尚未写入日志

在我看来,我有两个选择:

首先浏览消息:我知道我可以在获取消息之前浏览消息,尽管我对这会如何影响队列中的消息数量以及是否会创建重复消息等有点困惑

将消息写回队列A:理论上,如果我们从队列A获取消息,如果由于某种原因无法连接到队列B,那么将其放回队列A应该不会有问题

有人能先澄清一下浏览信息的正确方式吗?或者建议我没有想到的第三种方式

while (true) {

  try {

    // Clear the MQMessage
    theMessage.messageId = MQConstants.MQMI_NONE;
    theMessage.correlationId = MQConstants.MQCI_NONE;

    // Get the message from queue A
    queueA.get(theMessage, gmo);

    // Read the message from queue A
    byte[] messageBytes = new byte[theMessage.getMessageLength()];
    theMessage.readFully(messageBytes);
    String messageText = new String(messageBytes);

    // Store the message to the logs in case of crash

    // Put the message in queue B
    queueB.put(theMessage);

  } catch (MQException e) {

    // Break the loop if we get an MQException
    // Hopefully, it is a reason code 2033 (out of messages)

  } catch (IOException e) {

    // Something went wrong reading the message

  }
}


通常,如果您想跟踪读写的消息,应该使用事务性读写

MQGetMessageOptions gmo = new MQGetMessageOptions();   
gmo.waitInterval = 1000;
gmo.options = MQGMO_WAIT;
gmo.options += MQGMO_FAIL_IF_QUIESCING;
gmo.options += MQGMO_SYNCPOINT;

MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options += MQPMO_SYNCPOINT;

// create message instance
MQMessage message = new MQMessage();
message.correlationId = MQCI_NONE;
message.messageId = MQMI_NONE;

// read message
queueA.get(message, gmo);

// write message
queueB.put(message, pmo);

// commit transaction
qmgr.commit();
在这种情况下,若不提交事务,所有读取的消息将返回到源队列,所有写入的消息将从目标队列中消失。不是每封邮件都提交一次,而是每10封或100封,这取决于邮件的数量


如果您不打算使用分布式事务(例如,将MQ消息中的一些信息保存到数据库),这就足够了。否则,我建议切换到JMS,因为它具有更好的事务支持。

一般来说,如果您想跟踪消息的读写,应该使用事务读写

MQGetMessageOptions gmo = new MQGetMessageOptions();   
gmo.waitInterval = 1000;
gmo.options = MQGMO_WAIT;
gmo.options += MQGMO_FAIL_IF_QUIESCING;
gmo.options += MQGMO_SYNCPOINT;

MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options += MQPMO_SYNCPOINT;

// create message instance
MQMessage message = new MQMessage();
message.correlationId = MQCI_NONE;
message.messageId = MQMI_NONE;

// read message
queueA.get(message, gmo);

// write message
queueB.put(message, pmo);

// commit transaction
qmgr.commit();
在这种情况下,若不提交事务,所有读取的消息将返回到源队列,所有写入的消息将从目标队列中消失。不是每封邮件都提交一次,而是每10封或100封,这取决于邮件的数量


如果您不打算使用分布式事务(例如,将MQ消息中的一些信息保存到数据库),这就足够了。否则,我建议切换到JMS,因为它具有更好的事务支持。

如何切换取决于您使用的是连接还是JMSContext,但本质上是将get和put包装到事务中,并且在put成功后提交,或者在失败时回滚。您是使用IBM MQ类进行Java还是使用IBM MQ类进行JMS?根据你发布的有限代码,它似乎是前者。如果是这样,只需为GET添加MQGMO_同步点,并在PUT上添加MQPMO_同步点,一旦PUT完成,则发出qmgr.commit。这假设GET和PUT是到同一个队列管理器的。@如果您是正确的,我将尝试一下。我使用的是同一个队列管理器。如何操作取决于您使用的是连接还是JMSContext,但本质上是将get和put包装到事务中,并在put成功后提交,或者在put失败时回滚。您是使用IBM MQ classes for Java还是IBM MQ classes for JMS?根据你发布的有限代码,它似乎是前者。如果是这样,只需为GET添加MQGMO_同步点,并在PUT上添加MQPMO_同步点,一旦PUT完成,则发出qmgr.commit。这假设GET和PUT是到同一个队列管理器的。@如果您是正确的,我将尝试一下。我使用相同的队列管理器。