Summary of several basic communication methods of ACTIVEMQ

Source: Internet
Author: User
Tags repetition

Brief introduction

In the previous article discussed several application system integration methods, found that the actual Message Queuing-oriented integration scheme is a more reasonable overall choice. Here, we first discuss a specific message queue ACTIVEMQ Basic communication method. ACTIVEMQ is an implementation of the JMS message Communication specification. In general, the most common types of message communication patterns defined in the message specification are publish-subscribe, point-to-point. In addition, by combining the specific applications of these patterns, we also derive a pattern of request responses when dealing with certain scenarios. Below, we discuss these several ways one by one.

Basic process

When discussing specific ways, let's take a look at the main process of using ACTIVEMQ to start a service.

In accordance with the JMS specification, we first need to obtain a JMS connection factory. Connection is created through this connection factory. On this basis we create the session, destination, Producer and consumer. So the main steps are as follows:

1. Obtain the JMS connection factory. Construct factory by providing connection information for specific environments.

2. Structuring the JMS connection with factory

3. Start connection

4. Create a JMS session via connection.

5. Specify the JMS destination.

6. Create a JMS producer or create a JMS message and provide destination.

7. Create a JMS consumer or register JMS message listener.

8. Send and receive JMS message.

9. Close all JMS resources, including connection, session, producer, consumer, etc.

Publish-subscribe

The Publish subscription model is a bit like subscribing to newspapers in our daily lives. At the end of each year, the post Office sends a collection of newspapers. Let's choose which one to subscribe to. All the published newspapers are listed in the table, so we can choose one or more newspapers for each of our subscribers. such as Beijing Daily, Xiaoxiang morning news and so on. Then the newspapers we subscribe to are the equivalent of topic in the subscription model. There are many individuals who subscribe to newspapers, and others may subscribe to the same newspaper. Well, here, it's equivalent to registering in the same topic. For a newspaper issuer, it has a 1-to-many relationship with all subscribers. This relationship is as follows:

Now, suppose we write a simple example using the scenario discussed earlier. The first thing we need to define is publisher.

Publisher

Publisher is the party that publishes information by defining one or more topic and then sending messages to those topic.

Publisher's constructor is as follows:

Public Publisher () throws JMSException {    factory = new Activemqconnectionfactory (brokerurl);    Connection = Factory.createconnection ();    try {        connection.start ();    } catch (JMSException Jmse) {    connection.close ();    throw Jmse;    }        Session = Connection.createsession (false, Session.auto_acknowledge);        Producer = Session.createproducer (null);    }

We define the basic ConnectionFactory, connection, session, producer according to the process described above. Here the code is the main implementation of initialization effect.

Next, we need to define a series of topic for all the consumer to subscribe to and set the topic code as follows:

protected void Settopics (string[] stocks) throws jmsexception {destinations = new Destination[stocks.length];for (int i = 0 ; i < stocks.length; i++) {Destinations[i] = Session.createtopic ("STOCKS." + Stocks[i]);}}

Here destinations is an internally defined member variable destination[]. The total number of topic we have defined here depends on the given parameter stocks.

After defining the topic, we will send messages to these specified topic, with the following code:

protected void SendMessage (string[] stocks) throws JMSException {for (int i = 0; i < stocks.length; i++) {Message Messag E = Createstockmessage (Stocks[i], session); SYSTEM.OUT.PRINTLN ("Sending:" + ((activemqmapmessage) message). Getcontentmap () + "on destination:" + destinations[i]); Producer.send (Destinations[i], message);}} Protected message Createstockmessage (String stock, session session) throws JMSException {    Mapmessage message = Sessio N.createmapmessage (); Message.setstring ("Stock", "stock"), Message.setdouble ("Price", 1.00); Message.setdouble ("Offer ", 0.01); Message.setboolean (" Up ", true); return message;}

The preceding code is simple, in the SendMessage method we iterate through each topic and send a defined message message to each topic.

Once we've defined the basics of sending messages before, it's easy to call their code:

public static void Main (string[] args) throws JMSException {if (Args.length < 1) throw new IllegalArgumentException (); 
   //Create Publisher Publisher Publisher        = new publisher ();                Set topicspublisher.settopics (args); for (int i = 0; i <; i++) {publisher.sendmessage (args); System.out.println ("Publisher" + i + "price messages"); try {thread.sleep (1000);} catch (Interruptedexception e) {e.printstacktrace ();}    }    Close All Resources    publisher.close ();}

The code that calls them is we iterate through all the topic and send the message through SendMessage. Sleep1 seconds after a message is sent. One thing to note is that we have to use the Close method to release these resources after we have finished using the resources. The specific implementation of the Close method for closing resources is as follows:

public void Close () throws JMSException {    if (connection! = null) {        connection.close ();}     }

Consumer

Consumer code is similar, the specific step is nothing more than 1. Initialize the resource. 2. Receive the message. 3. Close the resource when necessary.

The initialization resource can be placed inside the constructor:

Public Consumer () throws JMSException {    factory = new Activemqconnectionfactory (brokerurl);    Connection = Factory.createconnection ();        Connection.start ();        Session = Connection.createsession (false, Session.auto_acknowledge);    }

There are two methods of receiving and processing messages, which are synchronous and asynchronous, and generally synchronous, we are processing the received message through the Messageconsumer.receive () method. The asynchronous approach is by registering a MessageListener method, using Messageconsumer.setmessagelistener (). Here we implement asynchronously:

public static void Main (string[] args) throws jmsexception {    Consumer Consumer = new Consumer ();    for (String Stock:args) {Destination Destination = Consumer.getsession (). Createtopic ("STOCKS." + stock); Messageconsumer Messageconsumer = Consumer.getsession (). Createconsumer (destination); Messageconsumer.setmessagelistener (New Listener ());}    } Public session getsession () {return session;}

In the previous code we found the same topic and then traversed all the topic to get the message. We are responsible for the processing of the messages through the Listener object.

The responsibility of the listener object is simple, mainly to handle the received message:

public class Listener implements MessageListener {public void onMessage (message message) {try {mapmessage map = (Mapmessag e) message; String stock = map.getstring ("Stock");d ouble price = map.getdouble ("price");d ouble offer = map.getdouble ("offer"); Boolean up = Map.getboolean ("Up");D ecimalformat df = new DecimalFormat ("#,###,###,# #0.00"); SYSTEM.OUT.PRINTLN (stock + "T" + df.format (price) + "\ T" + df.format (offer) + "\ T" + (up? ") Up "," Down ")); catch (Exception e) {e.printstacktrace ();}}}

It implements the MessageListener interface, where the OnMessage method is the method that will be called after the message is received.

Now, by implementing the previous publisher and consumer we have implemented an instance of the pub-sub pattern. Think carefully about its steps, the main thing is to set up a common topic, with this topic after they can realize one side of the message received by the other party. In addition, in order to connect to the specific message server, the connection tcp://localhost:16161 is used as the path to define the activemqconnectionfactory. Create a producer from the session on the publisher side, create a destination based on the specified parameters, and then send messages and destination as arguments to the Producer.send () method. On the consumer side also to create a similar connection, session. Through the session to get destination, and then through Session.createconsumer (destination) to get a Messageconsumer object. With this messageconsumer we can choose whether to synchronize the receive message or register the listener.

P2p

It's easier to understand the process. It is like two people call, these two people are exclusive of this communication link. One party sends a message, the other party receives it, it's that simple. In real-world applications because there are multiple users on the use of peer-to link, its communication scenario is as follows:

Let's take a look at one-to-peer example:

In the context of the peer, the mutual communication between the two sides through a similar to the queue to communicate. The difference between the pub-sub and the front is that a topic has a sender and multiple receivers, while in the peer-to-peer queue there is only one sender and one receiver.

Sent by

Very similar to the previous example, the content that we need to initialize in our constructor is basically the same:

Public Publisher () throws JMSException {    factory = new Activemqconnectionfactory (brokerurl);    Connection = Factory.createconnection ();    Connection.start ();    Session = Connection.createsession (false, Session.auto_acknowledge);    Producer = Session.createproducer (null);}
Here's how to send a message:


public void SendMessage () throws JMSException {for    (int i = 0; i < jobs.length; i++)    {       String job = jobs[i] ;       Destination Destination = Session.createqueue ("JOBS." + job);       Message message = Session.createobjectmessage (i);       System.out.println ("Sending:id:" + ((objectmessage) message). GetObject () + "on queue:" + destination);       Producer.send (destination, message);}    }
Here we define an array of jobs, and iterate through this array to create a different job queue. This is equivalent to establishing multiple point-to-point communication links.

The initiator code for the message sender is as follows:

public static void Main (string[] args) throws jmsexception {    Publisher publisher = new publisher ();    for (int i = 0; i < i++) {        publisher.sendmessage ();        System.out.println ("Published" + i + "job messages"); try {            thread.sleep (+);        } catch (Interruptedexception x) {    e.printstacktrace ();        }    }    Publisher.close ();}
We send 10 messages here, and of course, in each SendMessage method, we actually send 10 for each queue.

Receiver

The receiver's code is simple, and one constructor initializes all the resources:

Public Consumer () throws JMSException {    factory = new Activemqconnectionfactory (brokerurl);    Connection = Factory.createconnection ();        Connection.start ();        Session = Connection.createsession (false, Session.auto_acknowledge);    }
There is also an object for registering message processing:


public static void Main (string[] args) throws jmsexception {    Consumer Consumer = new Consumer ();    for (String job:consumer.jobs) {    Destination Destination = Consumer.getsession (). Createqueue ("jobs." + job);    Messageconsumer Messageconsumer = Consumer.getsession (). Createconsumer (destination);    Messageconsumer.setmessagelistener (Job) (new Listener);    }    } Public session getsession () {return session;}
The specific registration of the object processing method and the previous or similar, the implementation of the MessageListener interface can be.
Import Javax.jms.message;import Javax.jms.messagelistener;import Javax.jms.objectmessage;public class Listener Implements MessageListener {private string job;public Listener (String job) {this.job = job;} public void OnMessage (message message) {try {//do something hereSystem.out.println (Job + "ID:" + ((objectmessage) message) . GetObject ());} catch (Exception e) {e.printstacktrace ();}}}
The code here is very similar to the implementation code in front of the pub-sub, so don't repeat it.

Now if we compare the implementation steps of the pub-sub and the peer-to mode, we will find that their basic process is similar, except in pub-sub to set topic through Createtopic, The communication queue is created through Createqueue. There is a lot of duplication between them, in the specific development process, we can do some engineering optimization? Don't worry, we'll talk about that later.

Request-response

Compared to the previous two ways, the Request-response communication method is common, but is not a mode provided by default. In both of the preceding modes, one party is responsible for sending the message and the other is dealing with it. Many of our actual applications are equivalent to a one should process that requires both parties to send messages to each other. It is also important to request-answer this communication mode. It is also very common to apply.

The request-response method is not a method of communication provided by the JMS canonical system by default, but is implemented by a little bit of skill on the basis of existing communication methods. is a typical interactive process for request-answer methods:

In JMS, if you want to implement the request/reply method, you can use the Jmsreplyto and Jmscorrelationid message headers to correlate the two sides of the communication. In addition, Queuerequestor and Topicrequestor can support a simple request/reply process.

Now, if we are going to implement a process like this, the process of sending a request message and waiting for the client to return the result is as follows:

Client Sidedestination tempdest = Session.createtemporaryqueue (); Messageconsumer Responseconsumer = Session.createconsumer (tempdest), ...//send a request: Message.setjmsreplyto (tempdest) Message.setjmscorrelationid (Mycorrelationid);p roducer.send (message);

The client creates a temporary queue and specifies the destination and Correlationid to send the return message in the sent message. Then, after the server that processed the message gets the message, it knows who to send it to. The approximate process for server side is as follows:

public void OnMessage (message request) {  message response = Session.createmessage ();  Response.setjmscorrelationid (Request.getjmscorrelationid ())  Producer.send (Request.getjmsreplyto (), response )}

Here we are registering the MessageListener with the server side, returning the information by setting the Correlationid and Jmsreplyto of the return information.

The above is the approximate program structure of both sending and receiving messages. The specific implementation code is as follows:

Public Client () {activemqconnectionfactory connectionfactory = new Activemqconnectionfactory ("tcp://localhost:6161        6 ");        Connection Connection;            try {connection = connectionfactory.createconnection ();            Connection.start ();            Session session = Connection.createsession (transacted, Ackmode);            Destination adminqueue = Session.createqueue (clientqueuename); Setup a message producer to send message to the queue the server was consuming from this.producer = session.cr            Eateproducer (Adminqueue);            This.producer.setDeliveryMode (deliverymode.non_persistent);  Create a temporary queue that this client would listen for responses on then create a consumer//that consumes Message from this temporary queue...for a real application a client should reuse//the same temp queue for EAC H message to the Server...one temp queue per client Destination Tempdest = Session.createteMporaryqueue ();            Messageconsumer Responseconsumer = Session.createconsumer (tempdest);            This class would handle the messages to the temp queue as well responseconsumer.setmessagelistener (this);            Now create the actual message, want to send textmessage txtmessage = Session.createtextmessage ();            Txtmessage.settext ("Myprotocolmessage");            Set the reply to field to the temp queue you created above, which is the queue of the server//will respond to            Txtmessage.setjmsreplyto (tempdest);  Set a correlation ID so if you get a response you know which sent message the response are for//if there are Never more than one outstanding message to the server then the//same correlation ID can is used for all the M Essages...if there is more than one outstanding//message to the server you would presumably want to associate The correlation ID with this//mEssage somehow...a Map works good String Correlationid = this.createrandomstring ();            Txtmessage.setjmscorrelationid (Correlationid);        This.producer.send (Txtmessage); } catch (JMSException e) {//handle the exception appropriately}}

The code here in addition to the initialization of the parameters in the constructor also set two destination, one is to send messages out of the destination, in Session.createproducer (adminqueue), this sentence set. The other one is to receive the message destination, through destination Tempdest = Session.createtemporaryqueue (); Responseconsumer = Session.createconsumer (tempdest); These two sentences specify the destination to receive the message. Here is a temporary queue to use. After specifying the communication queue that returns the message, we need to inform the server that it knows which queue to send the return message to. So Txtmessage.setjmsreplyto (tempdest); This part was specified, while Txtmessage.setjmscorrelationid (Correlationid); The main method is to ensure that the server side of each send back request can know which request is corresponding. Here a request and an answer are equivalent to the same serial number as the corresponding one.

At the same time, because the client receives the message returned by the server after sending the message, it also implements the function of a message receiver. Here's how to implement the MessageListener interface:

public void OnMessage (Message message) {        String messagetext = null;        try {            if (message instanceof textmessage) {                TextMessage textmessage = (textmessage) message;                MessageText = Textmessage.gettext ();                System.out.println ("MessageText =" + MessageText);            }        } catch (JMSException e) {            //handle the exception appropriately        }    }

Server:

Here the server side to execute the procedure and the client side, it is to receive the message, after receiving the message according to the provided Jmscorelationid to send the returned message:

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 (This.messageProtocol.handleProtocolMessage (MessageText));            }//set the correlation ID from the received message to be the correlation ID of the response message This lets the client identify which message "This was a response to if it had more than//one outstanding mes            Sage to the server Response.setjmscorrelationid (Message.getjmscorrelationid ()); Send the response to the Destination specified by the Jmsreplyto field of the received message,//this is pre        sumably a temporary queue created by the client This.replyProducer.send (Message.getjmsreplyto (), response); } catch (JMSException E) {//handle the exception appropriately}} 

In front, in the Replyproducer.send () method, Message.getjmsreplyto () Gets the destination to send the message back.

In addition, the information that sets the replyproducer that send the return information is implemented primarily in the constructor-related methods:

Public Server () {try {//this message broker is embedded brokerservice broker = new Brokerse            Rvice ();            Broker.setpersistent (FALSE);            BROKER.SETUSEJMX (FALSE);            Broker.addconnector (Messagebrokerurl);        Broker.start (); } catch (Exception e) {//handle the Exception appropriately}//delegating the handling of Messa Ges to another class, instantiate it before setting up JMS so it//is ready to handle messages THIS.MESSAGEP        Rotocol = new Messageprotocol ();    This.setupmessagequeueconsumer (); } private void Setupmessagequeueconsumer () {activemqconnectionfactory connectionfactory = new Activemqconnectio        Nfactory (Messagebrokerurl);        Connection Connection;            try {connection = connectionfactory.createconnection ();            Connection.start ();            This.session = Connection.createsession (this.transacted, Ackmode); Destination ADminqueue = This.session.createQueue (messagequeuename); Setup a message producer to respond to messages from clients, we'll get the destination//to send to from T            He jmsreplyto header field from a Message this.replyproducer = This.session.createProducer (null);            This.replyProducer.setDeliveryMode (deliverymode.non_persistent); Set up a consumer to consume messages off of the admin queue messageconsumer consumer = This.session.createCo            Nsumer (Adminqueue);        Consumer.setmessagelistener (this); } catch (JMSException e) {//handle the exception appropriately}}

Overall, the whole process of interaction is not complex, but rather cumbersome. For a request/answer approach, this typical interaction is the client side setting up a temporary queue while setting the queue for normal send requests. Also specify the destination and Corelationid to return messages in the message you want to send, which is like a receipt in a letter. According to this information, people will know how to answer your letter. For the server side, an additional producer is created, and the message is sent back using producer in the process of receiving the message. This series of processes looks much like the HTTP protocol inside the request-answer method, all in a question and answer.

Some applications and improvements

Looking back at the previous three basic forms of communication, we will find that they all have certain similarities, such as initializing ConnectionFactory, Connection, session, etc. Close these resources when you are finished using them. It is a simple repetition if every communication end that implements it is written in such a way. From the point of view of engineering, there is absolutely no need. So, what can we do to reduce this repetition?

A simple way is to encapsulate the creation and destruction of these objects through a factory method, and then simply get them by invoking the factory method. In addition, since the basic process is created at the beginning of the resource at the end of the destruction, we can also adopt template method mode of thinking. By inheriting an abstract class, the encapsulation of resources is provided in the abstract class. All inherited classes can be implemented as long as they implement how to use these resources. The jmstemplate in the middle of spring provides this kind of thought-like encapsulation. The specific implementation can refer to this article.

Summarize

The ACTIVEMQ default provides a way for pub-sub to peer into these two types of communication. It also provides some support for the request-response approach. In fact, not only ACTIVEMQ, it provides similar functionality to all other products that implement the JMS specification. Each of these approaches is less complex, and the main reason is that the steps to create and manage resources appear cumbersome.

Resources

Activemq in action

Http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html

http://zorro.blog.51cto.com/2139862/831986

Summary of several basic communication methods of ACTIVEMQ

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.