程式扎記: [ InAction Note ] Ch3. The stock portfolio example - Use case one/two

標籤

2015年8月3日 星期一

[ InAction Note ] Ch3. The stock portfolio example - Use case one/two

Preface: 
ActiveMQ provides all the features from the JMS specification and adds many more powerful features on top of that. This is depicted in figure 3.1 and these features will be discussed through the rest of the book. In order to best demonstrate these features, two new examples have been created that are modeled after real business domains. Compared to the example that’s part of the ActiveMQ distribution, these examples lend themselves to demonstrating the features in ActiveMQ in a more complete and easy manner. 
 
Figure 3.1 ActiveMQ implements all the features from the JMS specification, as well as many additional features. 

One of the examples is based on a stock portfolio and the other is based on a job queue. These two examples are more extensive than the examples that come with ActiveMQ. The use case for each of these examples is introduced briefly, followed by a deeper discussion of how to use them. You can refer back to this chapter at any time throughout the book if you need a refresher on the examples. 

For the source code used in this chapter, you can download from here

Downloading Maven and compiling the examples: 
Here are the steps to download and install Maven: 
1. Download Maven from the Apache Software Foundation: http://maven.apache.org/ 
Maven is provided in both tarball and zip format, depending on your operating system.

2. Expand the downloaded archive to a permanent location on your computer. 

3. Create an environment variable named M2_HOME that points to the Maven directory. 

4. On Unix, add the $M2_HOME/bin directory to the PATH environment variable 
On Windows, add the %M2_HOME%\bin directory to the %PATH% environment variable.

5. Verify the Maven installation by running the following command from the command line: 

If you’ve successfully installed Maven, the examples need to be unzipped and compiled. After expanding the zip file containing the example source code, you’ll be ready to compile the examples. To do so, move into the amq-in-action-example-src directory and run the command shown next. 
$ mvn clean install
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 27.915s
[INFO] Finished at: Fri Jun 28 17:32:09 CST 2013
[INFO] Final Memory: 20M/208M
[INFO] ------------------------------------------------------------------------

As long as you see the BUILD SUCCESSFUL message, you’re ready to move on to the next section. If, on the other hand, you see the BUILD FAILURE message, you’ll need to troubleshoot and correct the situation before proceeding. 

Use case one: the stock portfolio example: 
As mentioned earlier in the chapter, the first use case revolves around a stock portfolio use case for demonstrating publish/subscribe messaging. This example is simple and utilizes a Publisher class for sending stock price messages to a topic, as well as a Consumer class for registering a Listener class to consume messages from topics in an asynchronous manner. These three classes embody the functionality of generating ever-changing stock prices that are published to topics on which the consumer is subscribed. 

In this example, stock prices are published to an arbitrary number of topics. The number of topics is based on the number of arguments sent to the Publisher and the Consumer on the command line. Each class will dynamically send and receive to/from the topics (an example is provided next). Take a look at figures 3.2 and 3.3 to see at a high level what the examples seek to achieve. 
 

For the sake of this demonstration, two topics will be used. The Publisher class uses a single JMS MessageProducer to send 1,000 fictitious stock price messages in blocks of 10, randomly distributed across the topics named in the command-line argument. After it sends 1,000 messages, it shuts down. The Consumer class creates one JMS MessageConsumer per topic and registers a JMS MessageListener for each topic. Because this example demonstrates publish/subscribe, theConsumers must be online to consume messages being sent by the Publisher, because durable consumers aren’t used in the basic stock portfolio example. The next step is to actually run the example so that you can see them in action. 

Running the stock portfolio example 
There are three basic steps to running this example: 
1. Start up ActiveMQ
2. Run the Consumer class
3. Run the Publisher class

These steps appear to be simple, and they are. The only item of note is that the Consumer should be started before the Publisher, in order to receive all messages that are published. This is because this example demonstrates pub/sub messaging and topics won’t hold messages unless the consumer makes a durable subscription, and we’re not using durable subscriptions here. So let’s get started with the stock portfolio example. 

The first task is to open a terminal or command line and execute ActiveMQ. This only requires a single command as demonstrated in the following listing. 
- Listing 3.2 Start up ActiveMQ 
# ./bin/activemq console
INFO: Using default configuration
(you can configure options in one of these file: /etc/default/activemq /root/.activemqrc)
...
INFO | Apache ActiveMQ 5.8.0 (localhost, ID:nlg-System-Product-Name-60542-1372562414379-0:1) is starting
INFO | Listening for connections at: tcp://nlg-System-Product-Name:61616?maximumConnect...eformat.maxFrameSize=104857600
INFO | Connector openwire Started
INFO | Listening for connections at: amqp://nlg-System-Product-Name:5672?maximumConnect...eformat.maxFrameSize=104857600
INFO | Connector amqp Started
INFO | Apache ActiveMQ 5.8.0 (localhost, ID:nlg-System-Product-Name-60542-1372562414379-0:1) started
...

The next task is to open a second terminal or command line to execute the Consumer class. The Consumer is executed using the maven-exec-plugin (http://mng.bz/bf7g) by passing it some system properties as arguments using the exec.args property. An example of running the Consumer is shown next. 
- Listing 3.3 Run the stock portfolio consumer 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portlio.Consumer -Dexec.args="CSCO ORCL"

You can see in listing 3.3 that Maven downloads the necessary artifacts it needs to run the examples. Once this has completed, the Publisher can start up and begin publishing stock prices to the two topics named on the command line, CSCO and ORCL. These two topic names were picked at random and can be replaced with any Strings you desire. The important part is that the same arguments be used for both the Consumer and the Publisher (the Publisher is shown next) via the system property exec.args

Note that the output just seems to stop as the Consumer hangs there. This behavior is correct because it’s waiting for messages to arrive in the topics to be consumed. When the Publisher begins sending messages, the Consumer will begin to consume them. 

The next task is to open a third terminal or command line to execute the Publisher class. Note that the same arguments are used in exec.args that were used for executing the Consumer class earlier, because the maven-exec-plugin is used to execute the Publisher class as well. An example of running Publisher is shown here. 
- Listing 3.4 Running the stock portfolio publisher 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher -Dexec.args="CSCO ORCL"mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher -Dexec.args="CSCO ORCL"
...
Published '10' of '810' price messages
Sending: {price=68.89056608956119, stock=ORCL, offer=68.95945665565074, up=false} on destination: topic://STOCKS.ORCL
Sending: {price=69.3154075538087, stock=ORCL, offer=69.3847229613625, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=69.45456209041542, stock=ORCL, offer=69.52401665250584, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=69.98499082271229, stock=ORCL, offer=70.054975813535, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=70.53041987695255, stock=ORCL, offer=70.6009502968295, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=70.66257854745797, stock=ORCL, offer=70.73324112600542, up=true} on destination: topic://STOCKS.ORCL
Sending: {price=14.105505687785833, stock=CSCO, offer=14.119611193473617, up=false} on destination: topic://STOCKS.CSCO
Sending: {price=14.144019032938186, stock=CSCO, offer=14.158163051971123, up=true} on destination: topic://STOCKS.CSCO
Sending: {price=14.203766032492718, stock=CSCO, offer=14.217969798525209, up=true} on destination: topic://STOCKS.CSCO
Sending: {price=70.51895973601245, stock=ORCL, offer=70.58947869574845, up=false} on destination: topic://STOCKS.ORCL
...

When executing the Publisher class, Maven already has all the necessary dependencies from the earlier execution of the Consumer class, so nothing should be downloaded. The lower portion of the output shows the stock price messages being sent to the two topics in blocks of 10. The example output is truncated for space, so just know that the Publisher will run until it sends a total of 1,000 messages. 

After running the Publisher, if you switch back to the second terminal where the Consumer was started, you should see that it’s now consuming messages: 
...
CSCO 14.25 14.26 up
CSCO 14.22 14.23 down
CSCO 14.26 14.27 up
CSCO 14.40 14.41 up
ORCL 74.95 75.02 up
ORCL 74.23 74.31 down
ORCL 74.57 74.65 up
ORCL 74.83 74.90 up
CSCO 14.40 14.41 down
CSCO 14.47 14.48 up
ORCL 75.33 75.40 up
...

The preceding output comes from the Listener class that’s registered by the Consumer on the two topics named ORCL and CSCO. This output shows the consumption of the stock price messages from the same two topics to which the Publisher is sending messages. Once the Publisher reaches 1,000 messages sent, it’ll shut down. But the Consumer will continue to run and just hang there waiting for more messages to arrive on those two topics. You can press CTRL-C in the second terminal to shut down the Consumer at this point. 

Use case two: the job queue example: 
The second use case focuses on job queues to illustrate point-to-point messaging. This example uses a Producer class to send job messages to a job queue and aConsumer class for registering a Listener class to consume messages from queues in an asynchronous manner. These three classes provide the functionality necessary to show how JMS point-to-point messaging should work. The classes in this example are extremely similar to those used in the stock portfolio example. The difference between the two examples is the JMS messaging domain that each uses. 

The Producer class in this example sends messages to the JOBS.suspend and JOBS.delete queues and the Consumer class consumes. Figure 3.3 contains a high-level diagram of the job queue example’s functionality. 
 

The Producer class uses a single JMS MessageProducer to send 1,000 job messages in blocks of 10 randomly across the two queues. After sending 1,000 messages total, it’ll shut down. The Consumer class uses one JMS MessageConsumer per queue and registers a JMS MessageListener on each queue to utilize the message and output its contents. 

Running the job queue example 
The steps for executing the job queues example are nearly identical to the previous example: 
1. Start up ActiveMQ
2. Run the Producer class
3. Run the Consumer class

Again, these steps are simple, but there’s one exception to note. When using PTP messaging, queues will hold messages until they’re consumed or the messages expire. So the Producer can be started before the Consumer and the Consumer won’t miss any messages. 

Just as in the stock portfolio example, the first task is to start up ActiveMQ. You’ll be spared the output from this task, as it’s the same as shown before and none of the default configuration has been changed. Next, open a second terminal or command line to execute the Producer as shown here. 
- Listing 3.5 Running the job queue publisher 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.jobs.Publisher
...
Published '10' of '990' job messages
Sending: id: 1000990 on queue: queue://JOBS.suspend
Sending: id: 1000991 on queue: queue://JOBS.delete
Sending: id: 1000992 on queue: queue://JOBS.delete
Sending: id: 1000993 on queue: queue://JOBS.suspend
Sending: id: 1000994 on queue: queue://JOBS.delete
Sending: id: 1000995 on queue: queue://JOBS.suspend
Sending: id: 1000996 on queue: queue://JOBS.suspend
Sending: id: 1000997 on queue: queue://JOBS.suspend
Sending: id: 1000998 on queue: queue://JOBS.delete
Sending: id: 1000999 on queue: queue://JOBS.delete
Published '10' of '1000' job messages
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:43.129s
[INFO] Finished at: Sun Jun 30 12:58:09 CST 2013
[INFO] Final Memory: 10M/111M
[INFO] ------------------------------------------------------------------------

Note that no arguments are necessary to execute the Producer in listing 3.5. The Producer class contains two queues to which it publishes named delete and suspend; hence, the use of those words in the output. The Producer will continue until it sends a total of 1,000 messages to the two queues and then it’ll shut down. 

The third task is to open another terminal or command line and execute the Consumer to consume the messages from the two queues. This command is shown next. 
- Listing 3.6 Running the job queue consumer 
# mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch3.jobsonsumer
...
suspend id:1000990
delete id:1000991
delete id:1000992
suspend id:1000993
delete id:1000994
suspend id:1000995
suspend id:1000996
suspend id:1000997
delete id:1000998
delete id:1000999

The Consumer will run fast at first, consuming all the messages already on the queues. When it catches up to where the Producer is in sending the 1,000 messages, the Consumer slows down and keeps up with the Producer until it completes. When all the messages have been sent and the Producer shuts itself down, you’ll need to press CTRL-C in the third terminal where the Consumer is running to shut it down.

沒有留言:

張貼留言

網誌存檔

關於我自己

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