Is it a good practice to use JMS Temporary Queue for synchronous use?

后端 未结 7 876
有刺的猬
有刺的猬 2021-01-30 18:20

If we use JMS request/reply mechanism using \"Temporary Queue\", will that code be scalable?

As of now, we don\'t know if we will supporting 100 requests per second, or

7条回答
  •  离开以前
    2021-01-30 18:40

    Ive been facing the same problem and decided to pool connections myself inside a stateless bean. One client connection has one tempQueue and lays inside JMSMessageExchanger object (which contains connectionFactory,Queue and tempQueue), which is bind to one bean instance. Ive tested it in JSE/EE environments. But im not really sure about Glassfish JMS pool behaviour. Will it actually close JMS connections, obtained "by hand" after bean method ends?Am I doing something terribly wrong?

    Also Ive turned off transaction in client bean (TransactionAttributeType.NOT_SUPPORTED) to send request messages immediately to the request queue.

    package net.sf.selibs.utils.amq;
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.DeliveryMode;
    import javax.jms.Message;
    import javax.jms.MessageConsumer;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.Session;
    import javax.jms.TemporaryQueue;
    import lombok.Getter;
    import lombok.Setter;
    import net.sf.selibs.utils.misc.UHelper;
    
    public class JMSMessageExchanger {
    
        @Setter
        @Getter
        protected long timeout = 60 * 1000;
    
        public JMSMessageExchanger(ConnectionFactory cf) {
            this.cf = cf;
        }
    
        public JMSMessageExchanger(ConnectionFactory cf, Queue queue) {
            this.cf = cf;
            this.queue = queue;
        }
        //work
        protected ConnectionFactory cf;
        protected Queue queue;
        protected TemporaryQueue tempQueue;
        protected Connection connection;
        protected Session session;
        protected MessageProducer producer;
        protected MessageConsumer consumer;
        //status
        protected boolean started = false;
        protected int mid = 0;
    
        public Message makeRequest(RequestProducer producer) throws Exception {
            try {
                if (!this.started) {
                    this.init();
                    this.tempQueue = this.session.createTemporaryQueue();
                    this.consumer = this.session.createConsumer(tempQueue);
                }
                //send request
                Message requestM = producer.produce(this.session);
                mid++;
                requestM.setJMSCorrelationID(String.valueOf(mid));
                requestM.setJMSReplyTo(this.tempQueue);
                this.producer.send(this.queue, requestM);
                //get response
                while (true) {
                    Message responseM = this.consumer.receive(this.timeout);
                    if (responseM == null) {
                        return null;
                    }
                    int midResp = Integer.parseInt(responseM.getJMSCorrelationID());
                    if (mid == midResp) {
                        return responseM;
                    } else {
                        //just get other message
                    }
                }
    
            } catch (Exception ex) {
                this.close();
                throw ex;
            }
        }
    
        public void makeResponse(ResponseProducer producer) throws Exception {
            try {
                if (!this.started) {
                    this.init();
                }
                Message response = producer.produce(this.session);
                response.setJMSCorrelationID(producer.getRequest().getJMSCorrelationID());
                this.producer.send(producer.getRequest().getJMSReplyTo(), response);
    
            } catch (Exception ex) {
                this.close();
                throw ex;
            }
        }
    
        protected void init() throws Exception {
            this.connection = cf.createConnection();
            this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            this.producer = this.session.createProducer(null);
            this.producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            this.connection.start();
            this.started = true;
        }
    
        public void close() {
            UHelper.close(producer);
            UHelper.close(consumer);
            UHelper.close(session);
            UHelper.close(connection);
            this.started = false;
        }
    
    }
    

    The same class is used in client (stateless bean) and server (@MessageDriven). RequestProducer and ResponseProducer are interfaces:

    package net.sf.selibs.utils.amq;
    
    import javax.jms.Message;
    import javax.jms.Session;
    
    public interface RequestProducer {
        Message produce(Session session) throws Exception;
    }
    package net.sf.selibs.utils.amq;
    
    import javax.jms.Message;
    
    public interface  ResponseProducer extends RequestProducer{
        void setRequest(Message request);
        Message getRequest();
    }
    

    Also I`ve read AMQ article about request-response implementation over AMQ: http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html

提交回复
热议问题