程式扎記: [ InAction Note ] Ch4. Connecting ActiveMQ - Transport connectors

標籤

2015年8月11日 星期二

[ InAction Note ] Ch4. Connecting ActiveMQ - Transport connectors

Preface: 
Before discussing the details of connectors and their role in the overall ActiveMQ architecture, it’s important to understand connector URIs. Uniform resource identifiers(URIs), as a concept, aren’t new, and you’ve probably used them over and over again without realizing it. URIs were first introduced for addressing resources on the World Wide Web. The specification (http://mng.bz/8iPP) defines the URI as “a compact string of characters for identifying an abstract or physical resource.” Because of the simplicity and flexibility of the URI concept, they found their place in numerous internet services. Web URLs and email addresses we use every day are just some common examples of URIs in practice. 

Without going too deep into discussing URIs, let’s briefly summarize the URI structure. This will serve as an ideal introduction to URI usage in ActiveMQ in regard to connectors. Basically, every URI has the following string format: 
:

Consider the following URI: 
mailto:users@activemq.apache.org

Note that the mailto scheme is used, followed by an email address to uniquely identify both the service we’re going to use and the particular resource within that service. The most common form of URIs are hierarchical URIs, which take the following form: 
://

This kind of URI is used by web browsers to identify websites. It’s a type of URI known as a URL (Uniform Resource Locator). Below is an example: 
http://www.nabble.com/forum/NewTopic.jtp?forum=2356

Because of their flexibility and simplicity, URIs are used in ActiveMQ to address specific brokers through different types of connectors. If we go back to the examples discussed in chapter 3, you can see that the following URI was used to create a connection to the broker: 
tcp://localhost:61616

This is a typical hierarchical URI used in ActiveMQ, which translates to “create a TCP connection to the localhost on port 61616.” 

ActiveMQ connectors using this kind of simple hierarchical URI pattern are sometimes referred to as low-level connectors and are used to implement basic network communication protocols. Connector URIs use the scheme part to identify the underlying network protocol, the path element to identify a network resource (usually host and port), and the query element to specify additional configuration parameters for the connector. The anatomy of a URI is shown in figure 4.1. This URI extends the previous example by also telling the broker to log all commands sent over this connector (the trace=true part). This is just one example of an option that’s available on the TCP transport. 
 

The failover transport in ActiveMQ supports automatic reconnection as well as the ability to connect to another broker just in case the broker to which a client is currently connected becomes unavailable. As will be discussed in chapter 10, ActiveMQ makes this easy to use and configure through the use of composite URIs. These composite URIs are used to configure such automatic reconnection. In figure 4.2, you can see an example of a typical composite URI. 
 

Note that the scheme part or the URI now identifies the protocol being used (the static protocol will be described later in this chapter) and the scheme-specific part contains one or more low-level URIs that will be used to create a connection. Of course, every low-level URI and the larger composite URI can contain the query part providing specific configuration options for the particular connector. 

Transport connectors: 
In order to exchange messages, producers and consumers (clients) need to connect to the broker. This client-to-broker communication is performed through transport connectors. ActiveMQ provides an impressive list of protocols clients can use to exchange messages. The requirements of ActiveMQ users in terms of connectivity are diverse. Some users focus on performance, others on security, and so on. ActiveMQ tries to cover all these aspects and provide a connector for every use case. 

Here you’ll learn how transport connectors are configured in the ActiveMQ configuration files and adapt the stock portfolio example to demonstrate various connectors. In the following sections, we’ll go through protocols available for connecting to the broker over the network, as well as introduce the concept of the embedded broker and Virtual Machine Protocol used for communicating with brokers inside your application (a topic that will be continued in chapter 7). 

Configuring transport connectors 
From the broker’s perspective, the transport connector is a mechanism used to accept and listen to connections from clients. If you take a look at the ActiveMQ demo configuration file (conf/activemq-demo.xml), you’ll see the configuration snippet for transport connectors similar to the following example: 
 

As you can see, transport connectors are defined within the  element. You define particular connectors with the appropriate nested element. ActiveMQ simultaneously supports many protocols listening on different ports. The configuration for a connector must uniquely define the name and the URI attributes. In this case, the URI defines the network protocol and optional parameters through which ActiveMQ will be exposed for connectivity. The discoveryUri attribute as shown on the OpenWire connector is optional and will be discussed further in section 4.3.1

The preceding snippet defines four transport connectors. Upon starting up ActiveMQ using such a configuration file, you’ll see the following log in the console as these connectors start up: 


From the client’s perspective, the transport connector URI is used to create a connection to the broker in order to send and receive messages. Sending and receiving messages will be discussed in detail in chapter 7, but the following code snippet should be enough to demonstrate the usage of the transport connector URIs in Java applications: 
  1. ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");  
  2. Connection connection = factory.createConnection();  
  3. connection.start();  
  4. Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
Note in the preceding example that the transport connector URIs defined in ActiveMQ configuration are used by the client application to create a connection to the broker. In this case, the URI for the TCP transport is used. 

With this basic understanding of configuring transport connectors, it’s important to become aware of and understand the available transport connectors in ActiveMQ. But before we start explaining particular connectors, we must first adapt our stock portfolio example so it can be used with different transport connectors. 

Adapting the stock portfolio example 
Chapter 3 introduced a stock portfolio example that uses ActiveMQ to publish and consume stock exchange data. There, we used the fixed standard connector URI since we wanted to make those introductory examples as simple as possible. In this chapter, we’ll explain all protocols and demonstrate them by running the stock portfolio example using each of them. For that reason, we need to modify the stock portfolio example so it will work using any of the protocols. 

- Listing 4.1 is a modified version of the main() method from the stock portfolio publisher. 
  1. public static void main(String[] args) throws JMSException {  
  2.     if (args.length == 0) {  
  3.         System.err.println("Please define a connection URI!");  
  4.         return;  
  5.     }  
  6.     Publisher publisher = new Publisher(args[0]);  
  7.     String[] topics = new String[args.length - 1];  
  8.     System.arraycopy(args, 1, topics, 0, args.length - 1);  
  9.     while (total < 1000) {  
  10.         for (int i = 0; i < count; i++) {  
  11.             publisher.sendMessage(topics);  
  12.         }  
  13.         total += count;  
  14.         System.out.println("Published '" + count + "' of '" + total  
  15.                 + "' price messages");  
  16.         try {  
  17.             Thread.sleep(1000);  
  18.         } catch (InterruptedException x) {  
  19.         }  
  20.     }  
  21.     publisher.close();  
  22. }  
The preceding code ensures that the connector URI is passed as the first argument and extracts topic names from the rest of the arguments passed to the application. Now the stock portfolio publisher can be run with the following command: 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publher -Dexec.args="tcp://localhost:61616 CSCO ORCL"
...
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ activemq-in-action-examples ---
Sending: {price=25.645814499580244, stock=CSCO, offer=25.67146031407982, up=true} on destination: topic://STOCKS.CSCO
Sending: {price=63.44722134717986, stock=ORCL, offer=63.51066856852704, up=false} on destination: topic://STOCKS.ORCL
Sending: {price=63.533980017540316, stock=ORCL, offer=63.59751399755785, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=25.54922206156826, stock=CSCO, offer=25.574771283629826, up=false} on destination: topic://STOCKS.CSCO
Sending: {price=25.788763572191154, stock=CSCO, offer=25.81455233576334, up=true} on destination: topic://STOCKS.CSCO
Sending: {price=63.887901542717216, stock=ORCL, offer=63.95178944425993, up=true} on destination: topic://STOCKS.ORCL
...

Note that one more argument has been added to the publisher: the URL to be used to connect to the appropriate broker. 

The same principle can be used to modify the stock portfolio consumer. In the following listing, you’ll find the stock portfolio consumer’s main() method modified to accept the connection URI as a first parameter. 
- Listing 4.2 Modifying stock portfolio consumer to support various connector URIs 
  1. public static void main(String[] args) throws JMSException {  
  2.     if (args.length == 0) {  
  3.         System.err.println("Please define connection URI!");  
  4.         return;  
  5.     }  
  6.     Consumer consumer = new Consumer(args[0]);  
  7.     String[] topics = new String[args.length - 1];  
  8.     System.arraycopy(args, 1, topics, 0, args.length - 1);  
  9.     for (String stock : topics) {  
  10.         Destination destination = consumer.getSession().createTopic(  
  11.                 "STOCKS." + stock);  
  12.         MessageConsumer messageConsumer = consumer.getSession()  
  13.                 .createConsumer(destination);  
  14.         messageConsumer.setMessageListener(new Listener());  
  15.     }  
  16. }  
In order to achieve the same functionality as in the chapter 3 example, you should run the consumer with an extra URI argument. The following example shows how to do this: 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args="tcp://localhost:61616 CSCO ORCL"
...
ORCL 65.71 65.78 up
ORCL 66.07 66.14 up
ORCL 65.93 65.99 down
CSCO 23.30 23.33 up
...

Note that the message flow between the producer and the consumer is the same as in the original example. With these changes, the examples are now ready to be run using a variety of supported protocols. Let’s now dig into the particular transport connectors. In the following section we’ll see what options you have if you want to connect to the broker over the network.

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!