ActiveMQ实战篇之ActiveMQ实现request/reply模型(二)

ActiveMQ实现request/reply模型


实现思路

ActiveMQ实战篇之ActiveMQ实现request/reply模型(二)_第1张图片

首先,Client的Producer发出一个JMS message形式的request,request上附加了一些额外的属性:

  • correlation ID(用来和返回的correlation ID对比进行验证),
  • JMSReplyTo属性(放置jms message的destination,这样worker的Consumer获得jms message就能得到destination)

然后,Worker的consumer收到requset,处理request并用producer发出reply,destination就从requset的JMSReplyTo属性中得到

下面贴出Client和Server的代码:


Client

package com.tgb.activemq;

import java.util.UUID;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;

public class Client implements MessageListener {
    private BrokerService broker;
    private final String brokerUrl = "tcp://localhost:61616";
    private Connection connection;
    private Session session;
    private Queue tempDest;
    private MessageProducer producer;
    private MessageConsumer consumer;

    private final String requestQueue = "requestQueue";

    public void start() throws Exception {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
        connection = connectionFactory.createConnection();
        connection.start();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination adminQueue = session.createQueue(requestQueue);
        producer = session.createProducer(adminQueue);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        tempDest = session.createTemporaryQueue();
        consumer = session.createConsumer(tempDest);
        consumer.setMessageListener(this);
    }

    public void stop() throws Exception {
        producer.close();
        consumer.close();
        session.close();
        broker.stop();
    }

    public void request(String request) throws JMSException {
        System.out.println("Requesting: " + request);
        TextMessage txtMessage = session.createTextMessage();
        txtMessage.setText(request);
        txtMessage.setJMSReplyTo(tempDest);
        String correlationId = UUID.randomUUID().toString();
        txtMessage.setJMSCorrelationID(correlationId);
        this.producer.send(txtMessage);
    }

    public void onMessage(Message message) {
        try {
            System.out.println("Received response for: " + ((TextMessage) message).getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
              Client client = new Client();
              client.start();
              int i = 0;
              while (i++ < 10) {
               client.request("REQUEST-" + i);
              }
              Thread.sleep(3000); //wait for replies
              client.stop();
    }
}

Server

package com.tgb.activemq;

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

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;

public class Server implements MessageListener {
    private BrokerService broker;
    private final String brokerUrl = "tcp://localhost:61616";
    private Session session;
    private MessageProducer producer;
    private MessageConsumer consumer;
    private final String requestQueue = "requestQueue";

    public void start() throws Exception {
        createBroker();
        setupConsumer();
    }

    private void createBroker() throws Exception {
        broker = new BrokerService();
        broker.setPersistent(false);
        broker.setUseJmx(false);
        broker.addConnector(brokerUrl);
        broker.start();
    }

    private void setupConsumer() throws JMSException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
        Connection connection;
        connection = connectionFactory.createConnection();
        connection.start();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination adminQueue = session.createQueue(requestQueue);
        producer = session.createProducer(null);
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        consumer = session.createConsumer(adminQueue);

        consumer.setMessageListener(this);
    }

    public void stop() throws Exception {
        producer.close();
        consumer.close();
        session.close();
        broker.stop();
    }

    @Override
    public void onMessage(Message message) {
        try {
            TextMessage response = this.session.createTextMessage();
            if (message instanceof TextMessage) {
                TextMessage txtMsg = (TextMessage) message;
                String messageText = txtMsg.getText();
                response.setText(handleRequest(messageText));
            }
            response.setJMSCorrelationID(message.getJMSCorrelationID());
            producer.send(message.getJMSReplyTo(), response);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    public String handleRequest(String messageText) {
        return "Response to '" + messageText + "'";
    }

    public static void main(String[] args) throws Exception {
          Server server = new Server();
          server.start();
          System.out.println();
          System.out.println("Press any key to stop the server");
          System.out.println();
          System.in.read();
          server.stop();
         }

}

运行结果

Requesting: REQUEST-1
Requesting: REQUEST-2
Requesting: REQUEST-3
Requesting: REQUEST-4
Requesting: REQUEST-5
Requesting: REQUEST-6
Requesting: REQUEST-7
Requesting: REQUEST-8
Requesting: REQUEST-9
Requesting: REQUEST-10
Received response for: Response to 'REQUEST-1'
Received response for: Response to 'REQUEST-2'
Received response for: Response to 'REQUEST-3'
Received response for: Response to 'REQUEST-4'
Received response for: Response to 'REQUEST-5'
Received response for: Response to 'REQUEST-6'
Received response for: Response to 'REQUEST-7'
Received response for: Response to 'REQUEST-8'
Received response for: Response to 'REQUEST-9'
Received response for: Response to 'REQUEST-10'

总结:这种模型比起普通的request/reply模型,具有很好高的可用性和伸缩性

原因是如果单个server不足以处理大量请求,那么只需要添加更多的server就能很轻松解决这个问题,这些server甚至可以部署在不同的主机上,这样就避免了相同主机上server对资源的争夺,唯一的限制就是消息的最大吞吐量。

你可能感兴趣的:(ActivityMQ学习)