ActiveMQ 三

第三章:ActiveMQ例子

本章内容

·         介绍本书每一个示例

·         使用Maven来编译和运行这些例子

·         怎样使用这些例子与ActiveMQ进行交互

ActiveMQ提供JMS规范要求的所有特性并且在这之上,提供了很多有用的特性。这些都在图3.1里描绘出来,并在本书剩下章节讨论。为了说明这些特性,我们提供了两个例子,这两个例子都是从真实商用领域得来的。相比前面的例子,这些例子更完整和简洁地展示ActiveMQ的特性。

其中一个例子是基于股票投资的,另一个例子是基于工作队列。这两个例子比ActiveMQ自带的例子更广泛地展现ActiveMQ。我们先介绍这些例子的使用场景,接着详细讨论如何使用它们。在你阅读这本书的任何时候,如果你需要回顾这些例子,你都可以回来阅读这一章。

    股票投资例子演示了发布/订阅到消息传送领域。发布者向许多对该消息感兴趣的订阅者广播消息。消息发布到一个叫做主题的JMS目标,在线的订阅者客户端则接收消息。通过这种方式,代理器向每一个订阅者发送消息而不用订阅者去拉消息。每一个在线的订阅者接收到一条消息的副本。除非使用持久订阅,否则订阅者必须在线等待接收消息。在一个主题中,将使用发布/订阅模式将消息的副本发送给每一个订阅者。

    工作队列例子演示里点对点消息传送领域。消息生产者发送消息到一个JMS队列,接收者则从这个队列接收消息。在点对点领域,消息的发送者和接收者没有时序性要求。队列会保存消息直到消费者准备好接收它们。如果消费者准备好,消息将发送给所有消费者,但是不会有两个或以上消费者接收到同一条消息。在点对点领域,队列里的消息通过循环方式发送到消费者。

    不只是不同例子关注的消息传送领域不同,它们对应的使用场景也不同。另外,虽然接下来的例子看起来差不多,但是它们有一个很重要的不同就是应用于不同的消息传送领域。股票投资使用发布/订阅消息传送,而工作队列使用点对点的消息传送。这些例子的代码可以从Manning网站下载,URLhttp://manning.com/snyder/activemq-in-action-examples-src.zip

    在这一章,首先我们会下载Maven并安装它,然后用它来编译和运行示例。之后,我们将回顾每一个例子并解释每一个例子的行为。在完成这些练习后,你将对这些例子有足够的了解可以在本书的其它部分认出它们,并且看看它们是如何被用来演示ActiveMQ特性。

 

3.1 下载Maven并编译例子

下面是下载和安装Maven的步骤:

1.    Apache Sofeware Foundation下载MavenURLhttp://maven.apache.org/Maven提供tarzip包,依据你操作系统选择不同的包。

2.    在你的计算机上将压缩包解压到一个永久路径。

3.    创建一个环境变量M2_HOME,并让它指向Maven目录

4.    Unix上,将$M2_HOME/bin目录添加到环境变量(在Windows上,将$M2_HOME/bin目录添加到%PATH%变量里)

5.    通过运行如下命令确认Maven正确安装。

         $ mvn -version
         Apache Maven 2.2.1 (r801777; 2009-08-06 13:16:01-0600)
         Java version: 1.5.0_19
         Java home: /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home
         Default locale: en_US, platform encoding: MacRoman
         OS name: "mac os x" version: "10.6.2" arch: "i386" Family: "unix"

         如果Maven正确安装,你将看到与上面相似的输出。如果没看到相似输出,你必须先使它正确再进入下一步。你  

         可以在下面的地址获取更多关于安装Maven的说明.http://maven.apache.org/download.html#Installation

 

你必须有因特网连接

要使用这些例子,你必须有因特网连接。因为Maven必须为这些例子下载必须的依赖包。

 

如果你已经成功安装Maven,现在必须解压和编译这些例子了。在把包含源代码的例子解压后,你就可以编译了。现在移动到amq-in-action-example-src目录,然后运行下面的命令。为了将命令与输出区分开,下面的命令将用粗体字显示。

[amq-in-action-example-src] $ mvn clean install 
[INFO] Scanning for projects...
[INFO] -------------------------------------------------------------------
-----
[INFO] Building ActiveMQ in Action Examples
[INFO] task-segment: [clean, install]
[INFO] -------------------------------------------------------------------
-----
Downloading: http://localhost:8081/nexus/content/groups/public/org/apache/
maven/plugins/maven-clean-plugin/2.2/maven-clean-plugin-2.2.pom
3K downloaded (maven-clean-plugin-2.2.pom)
...
[INFO] [install:install {execution: default-install}]
[INFO] Installing /private/tmp/amq-in-action-example-src/target/
activemq-in-action-examples.jar to /Users/bsnyder/.m2/repository/org/
apache/activemq/book/activemq-in-action-examples/1.0-SNAPSHOT/

activemq-in-action-examples-1.0-SNAPSHOT.jar
[INFO] Installing /private/tmp/amq-in-action-example-src/target/
activemq-in-action-examples-src.zip to /Users/bsnyder/.m2/repository/org/
apache/activemq/book/activemq-in-action-examples/1.0-SNAPSHOT/
activemq-in-action-examples-1.0-SNAPSHOT-src.zip
[INFO] -------------------------------------------------------------------
-----
[INFO] BUILD SUCCESSFUL
[INFO] -------------------------------------------------------------------
-----
[INFO] Total time: 57 seconds
[INFO] Finished at: Fri Dec 04 22:35:57 MST 2009
[INFO] Final Memory: 24M/44M
[INFO] -------------------------------------------------------------------
-----

由于输出信息太多,上面省略了一些。上面的信息说明了编译成功。当你看到BUILD SUCCESSFUL信息的时候,你就可以进入下面的学习了。如果你看到BUILD FAILURE,你必须找出出错原因并且解决后才能进入下一步。

3.2用例一:股票投资例子

就像之前提到的,我们第一个用例是使用股票投资的例子来展示发布/订阅的消息传送机制。这个例子使用一个Publisher类来发送一条股票价格消息到一个主题,同时,注册了ListenerConsumer类用异步方式从主题消费消息。这三个类体现了如何产生不停变换的股票消息并发送到被消费者订阅到主题上。

    在这个例子中,股票价格被发布的任意数量的主题上。主题的数量是由命令行携带给发布者和消费者的参数数量决定的。每一个类会动态地向/从主题发送或接收消息。图3.23.3在一个高层次上展示了这些例子要达到的目的。

    为了这个演示,两个主题将被使用。Publisher类使用一个单独的JMS MessageProducer以每次10条的方式去发送1000虚拟的股票消息,并随机地发送到由命令行参数所指明的各个主题上。发送完1000条消息,它将被关闭。Consumer类对每个主题都创建了一个MessageConsumer并且注册一个JMS MessageListener。因为这个例子是演示发布/订阅消息的,所以消费者必须在线消费消息(这个例子不使用持久订阅。)。下一步是真正地运行这个例子,这样你就能看到它们的动作了。

3.2.1运行股票投资例子

运行例子有以下步骤:

1.    启动ActiveMQ

2.    运行Consumer

3.    运行Publisher

这些步骤看起来很简单。要注意的是,Consumer类必须比Publisher类先启动,这样它才能接收到所有的消息。这是因为这个例子是用来演示发布/订阅消息模式的,所以主题并不会为客户端保存消息(我们没有用持久订阅)。现在让我们开始这个例子吧。

    首先,我们要打开一个终端或者命令行来运行ActiveMQ。这个只需一条命令,如下所示:

Listing 3.2 Start up ActiveMQ

[apache-activemq-5.4.1] $ ./bin/activemq console 
INFO: Using default configuration
(you can configure options in one of these file:
/etc/default/activemq /Users/bsnyder/.activemqrc)
INFO: Invoke the following command to create a configuration file
./bin/activemq setup [/etc/default/activemq | /Users/bsnyder/.activemqrc]
INFO: Using java
'/System/Library/Frameworks/JavaVM.framework/Home/bin/java'
INFO: Starting in foreground, this is just for debugging purposes
(stop process by pressing CTRL+C)
Java Runtime: Apple Inc. 1.6.0_20
/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
Heap sizes: current=258880k free=253105k max=258880k
JVM args: -Xms256M -Xmx256M

-Dorg.apache.activemq.UseDedicatedTaskRunner=true
-Djava.util.logging.config.file=logging.properties
-Dcom.sun.management.jmxremote
-Dactivemq.classpath=/Users/bsnyder/amq/apache-activemq-5.4.1/conf;
-Dactivemq.home=/Users/bsnyder/amq/apache-activemq-5.4.1
-Dactivemq.base=/Users/bsnyder/amq/apache-activemq-5.4.1
ACTIVEMQ_HOME: /Users/bsnyder/amq/apache-activemq-5.4.1
ACTIVEMQ_BASE: /Users/bsnyder/amq/apache-activemq-5.4.1
Loading message broker from: xbean:activemq.xml
...
INFO | Started [email protected]:8161

 

下一个任务是打开第二个终端(或命令行)来运行Consumer类。我们使用maven-exec-plugin来运行Consumer类。使用这个plugin时我们通过exec.args属性来传递一些系统参数。运行Consumer的例子如下:

Listing 3.3 Run the stock portfolio consumer

[amq-in-action-example-src] $ mvn exec:java \ -
Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Consumer \ -
Dexec.args="CSCO ORCL"
 
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] org.apache.maven.plugins: checking for updates from central
[INFO] org.codehaus.mojo: checking for updates from central
[INFO] artifact org.codehaus.mojo:exec-maven-plugin: checking for
updates from central
[INFO] snapshot org.codehaus.mojo:exec-maven-plugin:1.1.2-SNAPSHOT:
checking for updates from public-snapshots
[INFO] snapshot org.codehaus.mojo:exec-maven-plugin:1.1.2-SNAPSHOT:
checking for updates from central
Downloading:
http://localhost:8081/nexus/content/groups/public/org/codehaus/mojo/
exec-maven-plugin/1.1.2-SNAPSHOT/
exec-maven-plugin-1.1.2-20091120.114446-3.pom
4K downloaded (exec-maven-plugin-1.1.2-20091120.114446-3.pom)
Downloading:
http://localhost:8081/nexus/content/groups/public/org/codehaus/mojo/
mojo-parent/22/mojo-parent-22.pom
18K downloaded (mojo-parent-22.pom)
Downloading:
http://localhost:8081/nexus/content/groups/public-snapshots/org/codehaus/
mojo/exec-maven-plugin/1.1.2-SNAPSHOT/
exec-maven-plugin-1.1.2-20091120.114446-3.jar
36K downloaded (exec-maven-plugin-1.1.2-20091120.114446-3.jar)
[INFO] -------------------------------------------------------------------
-----
[INFO] Building ActiveMQ in Action Examples
[INFO] task-segment: [exec:java]
[INFO] -------------------------------------------------------------------
-----
[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping

[WARNING] POM for 'woodstox:wstx-asl:pom:3.2.7:compile' is invalid.
Its dependencies (if any) will NOT be available to the current build.
Downloading:
http://localhost:8081/nexus/content/groups/public/org/apache/commons/
commons-exec/1.0.1/commons-exec-1.0.1.pom
7K downloaded (commons-exec-1.0.1.pom)
Downloading:
http://localhost:8081/nexus/content/groups/public/org/apache/commons/
commons-exec/1.0.1/commons-exec-1.0.1.jar
48K downloaded (commons-exec-1.0.1.jar)
[INFO] [exec:java {execution: default-cli}]

 

在列表3.3你可以看到Maven下载了一些运行例子必须的组件。当Consumer启动完毕,我们就可以启动Publisher并开始发送股票消息到两个有命令行参数指定的目标CSCOORCL。这两个名字是随机取的,你可以改为其它任意字符串。重要的是ConsumerPublisher必须使用相同的参数。

运行Consumer时构建错误

当你运行Consumer类时,如果你看到BUILD ERROR,那么你必须先编译源代码,然后再运行它。下面的命令可以用来编译源代码:$ mvn clean install    这个命令编译并打包源代码。之后你可以用原先的命令来运行Consumer类了。

注意,现在输出已经停了,看起来就像Consumer挂起来。这是正常的,因为它正在等待消息。当Publisher开始发送消息,Consumer就会开始消费它们。

 

在输出窗口为什么看到所有的组件都是从本地下载?

3.1接如果Maven正确安装,那么它会下载运行例子所需要所有组件。在第一个输出窗口你可以看到它在下载组件。注意到所有的组件都是从本地下载而不是从远程Maven库下载。这是因为这些例子已经被配置为使用一个叫做Nexus的位于本地计算机的Maven库。Nexus提供很多好处,其中一个是它可以作为远程Maven库的代理缓存所有已下载组件。在Maven第一次下载组件后,它们都被保存到本地缓存里。如果多次编译,Nexus从本地缓存提供组件,这加快了编译速度。更多关于Nexus的消息请看:http://nexus.sonatype.org/

 

接下来我们打开第三个终端来运行Publisher类。注意在exec.args中必须使用与原来运行Consumer相同的参数,因为maven-exec-plugin也会用这些参数来运行Publisher。下面是运行Publisher的例子。

Listing 3.4 Running the stock portfolio publisher

[amq-in-action-example-src] $ mvn exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch3.portfolio.Publisher \
-Dexec.args="CSCO ORCL"
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] -------------------------------------------------------------------
-----
[INFO] Building ActiveMQ in Action Examples
[INFO] task-segment: [exec:java]
[INFO] -------------------------------------------------------------------
-----
[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping
[WARNING] POM for 'woodstox:wstx-asl:pom:3.2.7:compile' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [exec:java {execution: default-cli}]
Sending: {offer=62.6861410176471, price=62.62351750014696, up=true,
stock=ORCL} on destination: topic://STOCKS.ORCL
Sending: {offer=55.508573596887715, price=55.45312047641131, up=true,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=62.527946513790205, price=62.46548103275745, up=false,
stock=ORCL} on destination: topic://STOCKS.ORCL
Sending: {offer=55.78778713074073, price=55.73205507566507, up=true,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=55.593918646251986, price=55.53838026598601, up=false,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=55.83360390719586, price=55.777826081114746, up=true,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=55.99233608275527, price=55.93639968307221, up=true,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=62.006501598331475, price=61.94455704129019, up=false,
stock=ORCL} on destination: topic://STOCKS.ORCL
Sending: {offer=55.53698948617822, price=55.48150797820003, up=false,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=61.43866500377897, price=61.377287716062916, up=false,
stock=ORCL} on destination: topic://STOCKS.ORCL
Published '10' of '10' price messages
Sending: {offer=55.466945358331216, price=55.41153382450671, up=false,
stock=CSCO} on destination: topic://STOCKS.CSCO
Sending: {offer=61.27694222131968, price=61.215726494824864, up=false,
stock=ORCL} on destination: topic://STOCKS.ORCL
...
Published '10' of '30' price messages
...

 

运行Publisher时,由于Maven在之前运行Consumer时已经下载了所有的依赖组件,所以无需再下载了。在输出窗口下半部分可以看到,股票价格消息每10条一组发送到了两个主题。由于输出太多,部分没有显示在上面,但是要知道Publisher将会一直运行直到发送完1000条消息。

    运行完Publisher,现在切换到第二个终端,你可以看到Consumer正在从主题上消费消息。

...
[INFO] [exec:java {execution: default-cli}]
ORCL 62.62 62.69 up
CSCO 55.45 55.51 up
ORCL 62.47 62.53 down
CSCO 55.73 55.79 up
CSCO 55.94 55.99 up
CSCO 55.41 55.47 down
ORCL 61.22 61.28 down
ORCL 61.42 61.48 up
...

输出的前缀是注册到ORCLCSCO主题上的监听器打印出来的。这个输出说明了现在正在消费由Publisher发送到两个主题的消息。当Publisher发送我1000条消息后,它将被关闭。但是Consumer仍会继续运行并挂起等待更多的消息。你可以在第二个终端按CTRL-C来关闭Consumer

    现在你已经看到ActiveMQ怎样以发布/订阅模式运行,下一节将展示它如何以点对点消息传送方式运行。

3.3用例二:工作队列

第二个例子通过工作队列来演示点对点的消息传送。这个例子使用Producer类来向工作队列发送消息,而注册了ListenerConsumer类则用异步的方式从队列消费消息。这3个类展示了基本的JMS点对点消息传送是如何工作的。这些类和上一个例子很相似,区别就是用在不同的消息传送领域。

    Producer类发送消息到JOBS.suspendJOBS.delete队列,Consumer则消费它们。图3.3在一个高层次描述了这个过程。

Producer使用一个单独的MessageProducer来发送1000条工作消息,每次10条,随机地发送到两个队列。发完1000条消息后关闭。Consumer类对每一个队列使用一个MessageConsumer并注册一个JMS MessageListener来使用消息并输出相关信息。

 

3.3.1 运行工作队列例子

运行工作队列的步骤几乎和前一个例子的步骤一样:

1.    启动ActiveMQ

2.    运行Producer

3.    运行Consumer

这些步骤都很简单,但有一个地方要注意。我们现在使用的是点对点消息传送,队列会保存消息直到它们被消费或者过期。所以即使Produce先于Consumer启动,Consumer也不会错失任何消息。

    就像股票投资例子一样,第一个步骤是启动ActiveMQ。这个步骤就不再详述了,因为它和之前完全一样。

    接上来,打开第二个终端或命令行窗口来运行Producer

Listing 3.5 Running the job queue publisher

[amq-in-action-example-src] $ mvn exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch3.jobs.Publisher
 
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] -------------------------------------------------------------------
-----
[INFO] Building ActiveMQ in Action Examples
[INFO] task-segment: [exec:java]
[INFO] -------------------------------------------------------------------
-----
[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping
[WARNING] POM for 'woodstox:wstx-asl:pom:3.2.7:compile' is invalid.

Its dependencies (if any) will NOT be available to the current build.
[INFO] [exec:java {execution: default-cli}]
Sending: id: 1000000 on queue: queue://JOBS.delete
Sending: id: 1000001 on queue: queue://JOBS.delete
Sending: id: 1000002 on queue: queue://JOBS.delete
Sending: id: 1000003 on queue: queue://JOBS.delete
Sending: id: 1000004 on queue: queue://JOBS.delete
Sending: id: 1000005 on queue: queue://JOBS.delete
Sending: id: 1000006 on queue: queue://JOBS.delete
Sending: id: 1000007 on queue: queue://JOBS.delete
Sending: id: 1000008 on queue: queue://JOBS.delete
Sending: id: 1000009 on queue: queue://JOBS.delete
Published '10' of '10' job messages
Sending: id: 1000010 on queue: queue://JOBS.delete
Sending: id: 1000011 on queue: queue://JOBS.suspend
...
Published '10' of '30' job messages
...

 

注意运行Producer时并不需要传递任何参数。Publisher类包含了两个队列deletesuspend。这清楚地显示在输出内容上。Producer会发送1000条消息然后关闭。

    接下来的任务是打开另一个终端或命令行窗口来运行ConsumerConsumer会从两个队列消费消息。这个命令如下:

Listing 3.6 Running the job queue consumer

[amq-in-action-example-src] $ mvn exec:java \
-Dexec.mainClass=org.apache.activemq.book.ch3.jobs.Consumer
 
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'exec'.
[INFO] -------------------------------------------------------------------
-----
[INFO] Building ActiveMQ in Action Examples
[INFO] task-segment: [exec:java]
[INFO] -------------------------------------------------------------------
-----
[INFO] Preparing exec:java
[INFO] No goals needed for project - skipping
[WARNING] POM for 'woodstox:wstx-asl:pom:3.2.7:compile' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [exec:java {execution: default-cli}]
suspend id:1000003
suspend id:1000010
suspend id:1000012
suspend id:1000013
suspend id:1000015
suspend id:1000022
suspend id:1000025
suspend id:1000027
delete id:1000000
delete id:1000001

delete id:1000002
delete id:1000004
delete id:1000005
...

 

一开始,Consumer会运行得很快,消费完队列里所有的消息。当它赶上Producer时,Consumer开始慢下来,然后和Producer同步,直到Producer发送完1000条消息。当所有的消息发送完后,Producer自动终止,而Consumer不会,你需要在第三个终端上按CTRL-C来停止它。

    工作队列的例子结束了。现在你看到了ActiveMQ是如何以点对点消息传送方式工作的。

 

3.4总结

对本书例子的简单介绍的目的在于--快速和专注。工作和投资的例子在商业领域是很常见的,但这只是消息传送领域大量例子中的两个。虽然这两个例子只是在一个较高层次演示了两种消息传送领域,但它们还有其它作用。通过使用ActiveMQ提供的特性,这两个例子将在本书剩下部分被修改。所以你会经常看到这两个例子,不过稍有不同而已。

    本书的第一部分(13章)先向你介绍了ActiveMQ,使你对ActiveMQ有一个高层次的理解。接下来是关注面向消息中间件和JMS规范。虽然这些主题不只是与ActiveMQ有关,但对于理解ActiveMQ很有帮助。你也看了一些例子,这些例子将在整本书中使用。第一部分的内容是掌握ActiveMQ的热身,第二部分你将学会对ActiveMQ的连接,持久化,安全等各个方面进行配置。

第二部分:配置标准ActiveMQ组件

使用ActiveMQ看起来很简单直接:启动它,发送消息,接收消息。但是你没有看到隐藏在这些步骤后面的细节。理解这些细节和自定义配置需要更多的例子来说明。虽然ActiveMQ提供了大量的配置选项,但是理解一些核心的选项对于大多数应用是很必要的。

    第二部分深入到ActiveMQ关键的配置选项,包括连接,消息持久化,安全。这三个主题是你使用ActiveMQ最先遇到的问题,所以率先理解它们很重要。
发布了41 篇原创文章 · 获赞 4 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章