对于Request-Reply模式中的Responder,应使用哪个队列来创建使用者?

时间:2019-05-31 17:50:19

标签: ibm-mq

例如,我有具有REQUESTQ和RESPONSEQ的IBM MQ,将请求提交给REQUESTQ时,我需要从RESPONSEQ获取响应。根据以下代码:

package requestReply;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;

import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;

/*
 * Implementation of requester class
 */
class Requestor implements Runnable {
       private Thread t;
       private String threadName;

       Requestor( String name){
           threadName = name;
           System.out.println("Creating Thread:" +  threadName );
       }

       public void run() {
            JmsConnectionFactory cf = null;
            Connection connection = null;
            Session session = null;
            Destination reqQ = null;
            Destination repQ = null;
            MessageProducer producer = null;
            MessageConsumer consumer = null;

            try {
              // Create a connection factory
              JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
              cf = ff.createConnectionFactory();

              // Set the properties
              cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_BINDINGS);
              cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM2");

              // Create JMS objects
              connection = cf.createConnection();
              session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

              // Create destination to send requests
              reqQ = session.createQueue("queue:///REQUESTQ");
              // Create destination to read replies
              repQ = session.createQueue("queue:///REPLYQ");

              // Create producer
              producer = session.createProducer(reqQ);

              // Create a request message
              Message requestMessage = session.createTextMessage("Requesting a service");
              // Tell the responder where to put replies.
              requestMessage.setJMSReplyTo(repQ);
              // Send it off
              producer.send(requestMessage);

              // Get only that reply that matches my request message id.
              String selector = "JMSCorrelationID='" + requestMessage.getJMSMessageID()+"'";

              // Create consumer with selector
              consumer = session.createConsumer(repQ, selector);

              // Start the connection
              connection.start();

              // Get the message
              Message receivedMessage = consumer.receive(35000);
              if(receivedMessage != null)
                  System.out.println("\nRequestor received message:\n" + receivedMessage);
              else
                  System.out.println("No message received");
            }catch(Exception ex){
                System.out.println(threadName);
                System.out.println(ex);
            }
       }

       // Start thread
       public void start ()
       {
          System.out.println("Starting " +  threadName );
          if (t == null)
          {
             t = new Thread (this, threadName);
             t.start ();
          }
       }

    }

/*
 * Implementation of Responder class
 */
class Responder implements Runnable {
       private Thread t;
       private String threadName;

       Responder( String name){
           threadName = name;
           System.out.println("Creating Thread: " +  threadName );
       }

       public void run() {
            JmsConnectionFactory cf = null;
            Connection connection = null;
            Session session = null;
            Destination reqQ = null;
            Destination repQ = null;
            MessageProducer producer = null;
            MessageConsumer consumer = null;

            try {
              // Create a connection factory
              JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
              cf = ff.createConnectionFactory();

              // Set the properties
              cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_BINDINGS);
              cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM2");

              // Create JMS objects
              connection = cf.createConnection();
              session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
              reqQ = session.createQueue("queue:///REQUESTQ");

              // Create consumer to read requests
              consumer = session.createConsumer(reqQ);

              // Start the connection
              connection.start();

              // Loop to read requests and respond
              while(true){
              Message receivedMessage = consumer.receive(35000);
              if(receivedMessage != null){
                  System.out.println("\nResponder received message:\n" + receivedMessage);
                  repQ = receivedMessage.getJMSReplyTo();
                  producer = session.createProducer(repQ);
                  Message requestMessage = session.createTextMessage("Responder service");
                  requestMessage.setJMSCorrelationID(receivedMessage.getJMSMessageID());
                  producer.send(requestMessage);
              }
              else
                  System.out.println("No message received");
              }
            }catch(Exception ex){
                System.out.println(threadName);
                System.out.println(ex);
            }
       }

       public void start ()
       {
          System.out.println("Starting " +  threadName );
          if (t == null)
          {
             t = new Thread (this, threadName);
             t.start ();
          }
       }

    }

public class ReqRep {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Requestor req = new Requestor( "Requester");
        req.start();

        Responder rep = new Responder( "Responder");
        rep.start();
    }
}

[代码从https://www.ibm.com/developerworks/community/blogs/messaging/entry/jms_request_reply_sample?lang=en]复制

我从这段代码中了解到,当Requestor线程向REQUESTQ提交请求时,Responder将从REQUESTQ中提取信息并重新发送到RESPONSEQ,因此Requestor可以从RESPONDERQ获得实际响应?

我之所以这样问,是因为当我实际尝试时,RequestorResponder总是挂起以获得响应,这对我来说很有意义,因为一旦请求位于REQUESTQ中,MQ服务已经摆脱了该消息,对其进行了处理并已推送到RESPONSEQ,并且由于Requester正在等待Responder,并且Responder无法提取任何内容来自REQUESTQ的内容,导致挂起。 (如果我错了,请纠正我)

1 个答案:

答案 0 :(得分:0)

在我的机器上对其进行了尝试,有时它可以按预期运行,有时挂起35秒钟,直到消息传播为止。

启动Responder时,这是一个计时问题。如果ConnectionSession设置得太早,它将看不到前receive中的消息,只有在等待的前35秒之后才能收到消息。为了克服这个问题,只需在req.start()rep.start()之间稍等一下,然后它就会持续工作。

我建议阅读IBM的官方教程,例如Point to point with JMS。另外,它使用JMS 2.0,使JMS编程更简单。