简体   繁体   English

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

[英]IBM MQQueue Safest way to get all messages

I have a simple java program to transfer messages from queue A to queue B using IBM MQ.我有一个简单的 java 程序,可以使用 IBM MQ 将消息从队列 A 传输到队列 B。

My program works fine, but what I am concerned about is losing messages.我的程序运行良好,但我担心的是丢失消息。 I know that .get() removes the message from queue A. So of course, there is a brief moment where I have "got" a message from queue A, and I have not yet placed it in queue B. If my program were to crash during this time - the message would be lost.我知道.get()会从队列 A 中删除消息。当然,有一小段时间我从队列 A 中“获得”了一条消息,但我还没有将其放入队列 B。如果我的程序是在此期间崩溃 - 消息将丢失。

To combat this, I am writing the current message to the logs.为了解决这个问题,我将当前消息写入日志。 Then, if the program crashes, we can enter the message back into the queue manually.然后,如果程序崩溃,我们可以手动将消息输入回队列。

However - what if the program crashes from an IOException ?但是 - 如果程序因IOException崩溃怎么办? Now the message is gone from queue A, has not been .put() in queue B, and hasn't been written to the logs.现在消息从队列 A 中消失了,没有在队列 B 中被.put() ,也没有被写入日志。

The way I see it, I have two options:在我看来,我有两个选择:

Browse the message first: I know that I can browse the message before "getting" it, although I'm a bit confused about how this affects the number of messages in the queue, and if it creates a duplicate etc.首先浏览消息:我知道我可以在“获取”消息之前浏览消息,尽管我对这如何影响队列中的消息数量以及是否会创建重复等感到有些困惑。

Write the message back to queue A: In theory, if we "get" the message from queue A, we shouldn't have a problem "putting" it back to queue A, if for some reason we can't connect to queue B.将消息写回队列 A:理论上,如果我们从队列 A 中“获取”消息,那么将其“放回”队列 A 应该没有问题,如果由于某种原因我们无法连接到队列 B .

Could someone clarify the proper way to browse a message first - or perhaps suggest a third option I haven't thought of?有人可以首先澄清浏览消息的正确方法 - 或者提出我没有想到的第三种选择?

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

  }
}

Generally, if you want to keep track of messages read and written, you should use transactional reading/writing.通常,如果您想跟踪读取和写入的消息,您应该使用事务性读/写。

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();

In that case, if transaction will not be committed, all read messages will return to the source queue and all written messages will disappear from target queues.在这种情况下,如果事务不会被提交,所有读取的消息将返回源队列,所有写入的消息将从目标队列中消失。 It may be good idea to commit not every message, but every 10 or 100 depending on their amount.最好不要提交每条消息,而是每 10 条或 100 条,具体取决于它们的数量。

If you're not going to use distributed transactions (eg saving some information from MQ messages to database), that would suffice.如果您不打算使用分布式事务(例如,将一些信息从 MQ 消息保存到数据库),那就足够了。 Otherwise I'd recommend to switch to JMS because of its better transaction support.否则我建议切换到 JMS,因为它有更好的事务支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM