﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Terry.B.Li           彬-文章分类-ActiveMQ</title><link>http://www.blogjava.net/libin2722/category/46220.html</link><description>虚其心，可解天下之问；专其心，可治天下之学；静其心，可悟天下之理；恒其心，可成天下之业。</description><language>zh-cn</language><lastBuildDate>Wed, 01 Sep 2010 15:28:36 GMT</lastBuildDate><pubDate>Wed, 01 Sep 2010 15:28:36 GMT</pubDate><ttl>60</ttl><item><title>ActiveMQ in Action(7)</title><link>http://www.blogjava.net/libin2722/articles/330631.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:29:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330631.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330631.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330631.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330631.html</trackback:ping><description><![CDATA[
		<p>2．6．7 Wildcards<br />    Wildcards用来支持联合的名字分层体系（federated name hierarchies）。它不是JMS规范的一部分，而是ActiveMQ的扩展。ActiveMQ支持以下三种wildcards：</p>
		<ul>
				<li>"." 用于作为路径上名字间的分隔符。</li>
				<li>"*" 用于匹配路径上的任何名字。</li>
				<li>"&gt;" 用于递归地匹配任何以这个名字开始的destination。</li>
		</ul>
		<p>   作为一种组织事件和订阅感兴趣那部分信息的一种方法，这个概念在金融市场领域已经流行了一段时间了。设想你有以下两个destination：</p>
		<ul>
				<li>PRICE.STOCK.NASDAQ.IBM （IBM在NASDAQ的股价）</li>
				<li>PRICE.STOCK.NYSE.SUNW （SUN在纽约证券交易所的股价）</li>
		</ul>
		<p>   订阅者可以明确地指定destination的名字来订阅消息，或者它也可以使用wildcards来定义一个分层的模式来匹配它希望订阅的destination。例如：</p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Subscription</strong>
								</td>
								<td>
										<strong>Meaning</strong>
								</td>
						</tr>
						<tr>
								<td>PRICE.&gt;</td>
								<td>Any price for any product on any exchange</td>
						</tr>
						<tr>
								<td>PRICE.STOCK.&gt;</td>
								<td>Any price for a stock on any exchange</td>
						</tr>
						<tr>
								<td>PRICE.STOCK.NASDAQ.*</td>
								<td>Any stock price on NASDAQ</td>
						</tr>
						<tr>
								<td>PRICE.STOCK.*.IBM</td>
								<td>Any IBM stock price on any exchange</td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<p>2．6．8 Async Sends<br />    ActiveMQ支持以同步（sync）方式或者异步（async）方式向broker发送消息。 使用何种方式对send方法的延迟有巨大的影响。对于生产者来说，既然延迟是决定吞吐量的重要因素，那么使用异步发送方式会极大地提高系统的性能。<br />   
 
ActiveMQ缺省使用异步传输方式。但是按照JMS规范，当在事务外发送持久化消息的时候，ActiveMQ会强制使用同步发送方式。在这种情况下，
每一次发送都是同步的，而且阻塞到收到broker的应答。这个应答保证了broker已经成功地将消息持久化，而且不会丢失。但是这样作也严重地影响了
性能。<br />    如果你的系统可以容忍少量的消息丢失，那么可以在事务外发送持久消息的时候，选择使用异步方式。以下是几种不同的配置方式：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j" start="1">
						<li>
								<span>
										<span>cf = </span>
										<span class="keyword">new</span>
										<span> ActiveMQConnectionFactory(</span>
										<span class="string">"tcp://locahost:61616?jms.useAsyncSend=true"</span>
										<span>);  </span>
								</span>
						</li>
						<li>
								<span>((ActiveMQConnectionFactory)connectionFactory).setUseAsyncSend(<span class="keyword">true</span><span>);  </span></span>
						</li>
						<li>
								<span>((ActiveMQConnection)connection).setUseAsyncSend(<span class="keyword">true</span><span>);  </span></span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>2．6．9 Dispatch Policies<br />2．6．9．1 Round Robin Dispatch Policy<br />   
 
在2．6．4小节介绍过ActiveMQ的prefetch机制，ActiveMQ的缺省参数是针对处理大量消息时的高性能和高吞吐量而设置的。所以缺省
的prefetch参数比较大，而且缺省的dispatch 
policies会尝试尽可能快的填满prefetch缓冲。然而在有些情况下，例如只有少量的消息而且单个消息的处理时间比较长，那么在缺省的
prefetch和dispatch 
policies下，这些少量的消息总是倾向于被分发到个别的consumer上。这样就会因为负载的不均衡分配而导致处理时间的增加。<br />    Round robin dispatch policy会尝试平均分发消息，以下是ActiveMQ配置文件的一个例子： </p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">destinationPolicy</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"FOO.&gt;"</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>        <span class="tag">&lt;</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>          <span class="tag">&lt;</span><span class="tag-name">roundRobinDispatchPolicy</span><span> </span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>        <span class="tag">&lt;/</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">destinationPolicy</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>2．6．9．2 Strict Order Dispatch Policy<br />   
 有时候需要保证不同的topic consumer以相同的顺序接收消息。通常ActiveMQ会保证topic 
consumer以相同的顺序接收来自同一个producer的消息。然而，由于多线程和异步处理，不同的topic 
consumer可能会以不同的顺序接收来自不同producer的消息。例如有两个producer，分别是P和Q。差不多是同一时间内，P发送了
P1、P2和P3三个消息；Q发送了Q1和Q2两个消息。两个不同的consumer可能会以以下顺序接收到消息： </p>
		<p>   consumer1: P1 P2 Q1 P3 Q2<br />    consumer2: P1 Q1 Q2 P2 P3<br />   
 Strict order dispatch policy 会保证每个topic 
consumer会以相同的顺序接收消息，代价是性能上的损失。以下是采用了strict order dispatch 
policy后，两个不同的consumer可能以以下的顺序接收消息：<br />    consumer1: P1 P2 Q1 P3 Q2<br />    consumer2: P1 P2 Q1 P3 Q2</p>
		<p>   以下是ActiveMQ配置文件的一个例子：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">destinationPolicy</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span> </span><span class="attribute">topic</span><span>=""</span><span class="attribute-value">FOO</span><span>.</span><span class="tag">&gt;</span><span>"</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>        <span class="tag">&lt;</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>          <span class="tag">&lt;</span><span class="tag-name">strictOrderDispatchPolicy</span><span> </span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>        <span class="tag">&lt;/</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">destinationPolicy</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>2．6．10 Message Cursors<br />   
 
当producer发送的持久化消息到达broker之后，broker首先会把它保存在持久存储中。接下来，如果发现当前有活跃的consumer，而
且这个consumer消费消息的速度能跟上producer生产消息的速度，那么ActiveMQ会直接把消息传递给broker内部跟这个
consumer关联的dispatch 
queue；如果当前没有活跃的consumer或者consumer消费消息的速度跟不上producer生产消息的速度，那么ActiveMQ会使用
Pending Message Cursors保存对消息的引用。在需要的时候，Pending Message 
Cursors把消息引用传递给broker内部跟这个consumer关联的dispatch queue。以下是两种Pending Message
 Cursors：</p>
		<ul>
				<li>VM Cursor。在内存中保存消息的引用。</li>
				<li>File Cursor。首先在内存中保存消息的引用，如果内存使用量达到上限，那么会把消息引用保存到临时文件中。</li>
		</ul>
		<p>   在缺省情况下，ActiveMQ 5.0根据使用的Message Store来决定使用何种类型的Message Cursors，但是你可以根据destination来配置Message Cursors。</p>   
 对于topic，可以使用的pendingSubscriberPolicy 
有vmCursor和fileCursor。可以使用的PendingDurableSubscriberMessageStoragePolicy有
vmDurableCursor 和 fileDurableSubscriberCursor。以下是ActiveMQ配置文件的一个例子：<br /><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"org.apache.&gt;"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">pendingSubscriberPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">vmCursor</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">pendingSubscriberPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">PendingDurableSubscriberMessageStoragePolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">vmDurableCursor</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">PendingDurableSubscriberMessageStoragePolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>   对于queue，可以使用的pendingQueuePolicy有vmQueueCursor 和 fileQueueCursor。以下是ActiveMQ配置文件的一个例子：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span> </span><span class="attribute">queue</span><span>=</span><span class="attribute-value">"org.apache.&gt;"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">pendingQueuePolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">vmQueueCursor</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">pendingQueuePolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．6．11 Optimized Acknowledgement<br />    ActiveMQ缺省支持批量确认消息。由于批量确认会提高性能，因此这是缺省的确认方式。如果希望在应用程序中禁止经过优化的确认方式，那么可以采用如下方法：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>cf = </span><span class="keyword">new</span><span> ActiveMQConnectionFactory (</span><span class="string">"tcp://locahost:61616?jms.optimizeAcknowledge=false"</span><span>);  </span></span></li><li><span>((ActiveMQConnectionFactory)connectionFactory).setOptimizeAcknowledge(<span class="keyword">false</span><span>);  </span></span></li><li><span>((ActiveMQConnection)connection).setOptimizeAcknowledge(<span class="keyword">false</span><span>);  </span></span></li></ol></div><p> </p><p>2．6．12 Producer Flow Control<br />   
 同步发送消息的producer会自动使用producer flow control 
；对于异步发送消息的producer，要使用producer flow 
control，你先要为connection配置一个ProducerWindowSize参数，如下： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>((ActiveMQConnectionFactory)cf).setProducerWindowSize(</span><span class="number">1024000</span><span>);  </span></span></li></ol></div>    ProducerWindowSize是producer在发送消息的过程中，收到broker对于之前发送消息的确认之前， 能够发送消息的最大字节数。你也可以禁用producer flow control，以下是ActiveMQ配置文件的一个例子：<div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>&lt;destinationPolicy&gt;  </span></span></li><li><span>  &lt;policyMap&gt;  </span></li><li><span>    &lt;policyEntries&gt;  </span></li><li><span>      &lt;policyEntry topic=<span class="string">"FOO.&gt;"</span><span> producerFlowControl=</span><span class="string">"false"</span><span>&gt;  </span></span></li><li><span>        &lt;dispatchPolicy&gt;  </span></li><li><span>          &lt;strictOrderDispatchPolicy/&gt;  </span></li><li><span>        &lt;/dispatchPolicy&gt;  </span></li><li><span>      &lt;/policyEntry&gt;  </span></li><li><span>    &lt;/policyEntries&gt;  </span></li><li><span>  &lt;/policyMap&gt;  </span></li><li><span>&lt;/destinationPolicy&gt;  </span></li></ol></div><p> </p><p>2．6．13 Message Transformation<br />    有时候需要在JMS provider内部进行message的转换。从4.2版本起，ActiveMQ 提供了一个MessageTransformer 接口用于进行消息转换，如下： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> MessageTransformer {  </span></span></li><li><span>    Message producerTransform(Session session, MessageProducer producer, Message message) <span class="keyword">throws</span><span> JMSException;  </span></span></li><li><span>    Message consumerTransform(Session session, MessageConsumer consumer, Message message)<span class="keyword">throws</span><span> JMSException;  </span></span></li><li><span>}  </span></li></ol></div>    通过在以下对象上通过调用setTransformer方法来设置MessageTransformer：<ul><li>ActiveMQConnectionFactory</li><li>ActiveMQConnection</li><li>ActiveMQSession</li><li>ActiveMQMessageConsumer</li><li>ActiveMQMessageProducer</li></ul><p>   MessageTransformer接口支持： </p><ul><li>在消息被发送到JMS provider的消息总线前进行转换。通过producerTransform方法。</li><li>在消息到达消息总线后，但是在consumer接收到消息前进行转换。通过consumerTransform方法。</li></ul><p>   以下是个简单的例子：    </p><p> </p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> SimpleMessage </span><span class="keyword">implements</span><span> Serializable {  </span></span></li><li><span>    <span class="comment">//</span><span>  </span></span></li><li><span>    <span class="keyword">private</span><span> </span><span class="keyword">static</span><span> </span><span class="keyword">final</span><span> </span><span class="keyword">long</span><span> serialVersionUID = 2251041841871975105L;  </span></span></li><li><span>      </span></li><li><span>    <span class="comment">//</span><span>  </span></span></li><li><span>    <span class="keyword">private</span><span> String id;  </span></span></li><li><span>    <span class="keyword">private</span><span> String text;  </span></span></li><li><span>      </span></li><li><span>    <span class="keyword">public</span><span> String getId() {  </span></span></li><li><span>        <span class="keyword">return</span><span> id;  </span></span></li><li><span>    }  </span></li><li><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setId(String id) {  </span></span></li><li><span>        <span class="keyword">this</span><span>.id = id;  </span></span></li><li><span>    }  </span></li><li><span>    <span class="keyword">public</span><span> String getText() {  </span></span></li><li><span>        <span class="keyword">return</span><span> text;  </span></span></li><li><span>    }  </span></li><li><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setText(String text) {  </span></span></li><li><span>        <span class="keyword">this</span><span>.text = text;  </span></span></li><li><span>    }  </span></li><li><span>}  </span></li></ol></div>    在producer内发送ObjectMessage，如下：<div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>SimpleMessage sm = </span><span class="keyword">new</span><span> SimpleMessage();  </span></span></li><li><span>sm.setId(<span class="string">"1"</span><span>);  </span></span></li><li><span>sm.setText(<span class="string">"this is a sample message"</span><span>);  </span></span></li><li><span>ObjectMessage message = session.createObjectMessage();  </span></li><li><span>message.setObject(sm);  </span></li><li><span>producer.send(message);  </span></li></ol></div><p>   在consumer的session上设置一个MessageTransformer用于将ObjectMessage转换成TextMessage，如下： </p><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>((ActiveMQSession)session).setTransformer(</span><span class="keyword">new</span><span> MessageTransformer() {  </span></span></li><li><span><span class="keyword">public</span><span> Message consumerTransform(Session session, MessageConsumer consumer, Message message) </span><span class="keyword">throws</span><span> JMSException {  </span></span></li><li><span>    ObjectMessage om = (ObjectMessage)message;  </span></li><li><span>    XStream xstream = <span class="keyword">new</span><span> XStream();  </span></span></li><li><span>    xstream.alias(<span class="string">"simple message"</span><span>, SimpleMessage.</span><span class="keyword">class</span><span>);  </span></span></li><li><span>    String xml = xstream.toXML(om.getObject());  </span></li><li><span>    <span class="keyword">return</span><span> session.createTextMessage(xml);  </span></span></li><li><span>}  </span></li><li><span>  </span></li><li><span><span class="keyword">public</span><span> Message producerTransform(Session session, MessageProducer consumer, Message message) </span><span class="keyword">throws</span><span> JMSException {  </span></span></li><li><span>    <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li><span>}  </span></li><li><span>}); <br /></span></li></ol><img src ="http://www.blogjava.net/libin2722/aggbug/330631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:29 <a href="http://www.blogjava.net/libin2722/articles/330631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(6)</title><link>http://www.blogjava.net/libin2722/articles/330629.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330629.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330629.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330629.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330629.html</trackback:ping><description><![CDATA[
		<p>2．6 Features<br />    ActiveMQ包含了很多功能强大的特性，下面简要介绍其中的几个。<br />2．6．1 Exclusive Consumer<br />   
 
Queue中的消息是按照顺序被分发到consumers的。然而，当你有多个consumers同时从相同的queue中提取消息时，你将失去这个保
证。因为这些消息是被多个线程并发的处理。有的时候，保证消息按照顺序处理是很重要的。例如，你可能不希望在插入订单操作结束之前执行更新这个订单的操
作。<br />    ActiveMQ从4.x版本起开始支持Exclusive Consumer （或者说Exclusive Queues）。 
Broker会从多个consumers中挑选一个consumer来处理queue中所有的消息，从而保证了消息的有序处理。如果这个consumer
失效，那么broker会自动切换到其它的consumer。<br />    可以通过Destination Options 来创建一个Exclusive Consumer，如下：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j" start="1">
						<li>
								<span>
										<span>queue = </span>
										<span class="keyword">new</span>
										<span> ActiveMQQueue(</span>
										<span class="string">"TEST.QUEUE?consumer.exclusive=true"</span>
										<span>);  </span>
								</span>
						</li>
						<li>
								<span>consumer = session.createConsumer(queue);  </span>
						</li>
				</ol>
		</div>    顺便说一下，可以给consumer设置优先级，以便针对网络情况（如network hops）进行优化，如下：<div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>queue = </span><span class="keyword">new</span><span> ActiveMQQueue(</span><span class="string">"TEST.QUEUE?consumer.exclusive=true &amp;consumer.priority=10"</span><span>);  </span></span></li></ol></div><p> </p><p>2．6．2 Message Groups<br />   
 用Apache官方文档的话说，Message Groups rock！它是Exclusive 
Consumer功能的增强。逻辑上，Message Groups 可以看成是一种并发的Exclusive 
Consumer。跟所有的消息都由唯一的consumer处理不同，JMS 消息属性JMSXGroupID 被用来区分message 
group。Message Groups特性保证所有具有相同JMSXGroupID 
的消息会被分发到相同的consumer（只要这个consumer保持active）。另外一方面，Message 
Groups特性也是一种负载均衡的机制。<br />    
在一个消息被分发到consumer之前，broker首先检查消息JMSXGroupID属性。如果存在，那么broker 
会检查是否有某个consumer拥有这个message 
group。如果没有，那么broker会选择一个consumer，并将它关联到这个message 
group。此后，这个consumer会接收这个message group的所有消息，直到：</p><ul><li>Consumer被关闭。</li><li>Message group被关闭。通过发送一个消息，并设置这个消息的JMSXGroupSeq为0。</li></ul><p>  
 从4.1版本开始，ActiveMQ支持一个布尔字段JMSXGroupFirstForConsumer 。当某个message 
group的第一个消息被发送到consumer的时候，这个字段被设置。如果客户使用failover 
transport连接到broker。在由于网络问题等造成客户重新连接到broker的时候，相同message 
group的消息可能会被分发到不同与之前的consumer，因此JMSXGroupFirstForConsumer字段也会被重新设置。  </p><p>   以下是使用message groups的例子：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>Mesasge message = session.createTextMessage(</span><span class="string">"&lt;foo&gt;hey&lt;/foo&gt;"</span><span>);  </span></span></li><li><span>message.setStringProperty(<span class="string">"JMSXGroupID"</span><span>, </span><span class="string">"IBM_NASDAQ_20/4/05"</span><span>);  </span></span></li><li><span>...  </span></li><li><span>producer.send(message);  </span></li></ol></div><br />2．6．3 JMS Selectors<br />    JMS Selectors用于在订阅中，基于消息属性对进行消息的过滤。JMS Selectors由SQL92语法定义。以下是个Selectors的例子：<br /><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>consumer = session.createConsumer(destination, </span><span class="string">"JMSType = 'car' AND weight &gt; 2500"</span><span>);  </span></span></li></ol></div>     在JMS Selectors表达式中，可以使用IN、NOT IN、LIKE等，例如：<br />    LIKE '12%3' （'123' true，'12993' true，'1234' false）<br />    LIKE 'l_se' （'lose' true，'loose' false）<br />    LIKE '\_%' ESCAPE '\' （'_foo' true，'foo' false）<br />    需要注意的是，JMS Selectors表达式中的日期和时间需要使用标准的long型毫秒值。另外表达式中的属性不会自动进行类型转换，例如：<br /><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>myMessage.setStringProperty(</span><span class="string">"NumberOfOrders"</span><span>, </span><span class="string">"2"</span><span>);  </span></span></li></ol></div>    "NumberOfOrders &gt; 1" 求值结果是false。关于JMS Selectors的详细文档请参考javax.jms.Message的javadoc。<br />   
 上一小节介绍的Message Groups虽然可以保证具有相同message 
group的消息被唯一的consumer顺序处理，但是却不能确定被哪个consumer处理。在某些情况下，Message 
Groups可以和JMS Selector一起工作，例如：<br />    
设想有三个consumers分别是A、B和C。你可以在producer中为消息设置三个message 
groups分别是"A"、"B"和"C"。然后令consumer A使用"JMXGroupID = 
'A'"作为selector。B和C也同理。这样就可以保证message group A的消息只被consumer 
A处理。需要注意的是，这种做法有以下缺点：<br /><ul><li>producer必须知道当前正在运行的consumers，也就是说producer和consumer被耦合到一起。</li><li>如果某个consumer失效，那么应该被这个consumer消费的消息将会一直被积压在broker上。</li></ul><p>2．6．4 Pending Message Limit Strategy<br />   
 
首先简要介绍一下prefetch机制。ActiveMQ通过prefetch机制来提高性能，这意味这客户端的内存里可能会缓存一定数量的消息。缓存消
息的数量由prefetch limit来控制。当某个consumer的prefetch 
buffer已经达到上限，那么broker不会再向consumer分发消息，直到consumer向broker发送消息的确认。可以通过在
ActiveMQConnectionFactory或者ActiveMQConnection上设置ActiveMQPrefetchPolicy对象
来配置prefetch policy。也可以通过connection options或者destination options来配置。例如：<br />    tcp://localhost:61616?jms.prefetchPolicy.all=50<br />    tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1<br />    queue = new ActiveMQQueue("TEST.QUEUE?consumer.prefetchSize=10");<br />    prefetch size的缺省值如下：</p><ul><li>persistent queues (default value: 1000)</li><li>non-persistent queues (default value: 1000)</li><li>persistent topics (default value: 100)</li><li>non-persistent topics (default value: Short.MAX_VALUE -1)</li></ul><p>   
 
慢消费者会在非持久的topics上导致问题：一旦消息积压起来，会导致broker把大量消息保存在内存中，broker也会因此而变慢。未来
ActiveMQ可能会实现磁盘缓存，但是这也还是会存在性能问题。目前ActiveMQ使用Pending Message Limit 
Strategy来解决这个问题。除了prefetch 
buffer之外，你还要配置缓存消息的上限，超过这个上限后，新消息到来时会丢弃旧消息。通过在配置文件的destination 
map中配置PendingMessageLimitStrategy，可以为不用的topic namespace配置不同的策略。目前有以下两种：</p><ul><li>ConstantPendingMessageLimitStrategy。这个策略使用常量限制。<br />例如：&lt;constantPendingMessageLimitStrategy limit="50"/&gt;</li><li>PrefetchRatePendingMessageLimitStrategy。这个策略使用prefetch size的倍数限制。<br />例如：&lt;prefetchRatePendingMessageLimitStrategy multiplier="2.5"/&gt;</li></ul><p>   在以上两种方式中，如果设置0意味着除了prefetch之外不再缓存消息；如果设置-1意味着禁止丢弃消息。  <br />    此外，你还可以配置消息的丢弃策略，目前有以下两种：</p><ul><li>oldestMessageEvictionStrategy。这个策略丢弃最旧的消息。</li><li>oldestMessageWithLowestPriorityEvictionStrategy。这个策略丢弃最旧的，而且具有最低优先级的消息。</li></ul><p>   以下是个ActiveMQ配置文件的例子： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">persistent</span><span>=</span><span class="attribute-value">"false"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"${brokername}"</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"PRICES.&gt;"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>            <span class="comments">&lt;!--  10 seconds worth --&gt;</span><span>  </span></span></li><li><span>            <span class="tag">&lt;</span><span class="tag-name">subscriptionRecoveryPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>              <span class="tag">&lt;</span><span class="tag-name">timedSubscriptionRecoveryPolicy</span><span> </span><span class="attribute">recoverDuration</span><span>=</span><span class="attribute-value">"10000"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>            <span class="tag">&lt;/</span><span class="tag-name">subscriptionRecoveryPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>              </span></li><li><span>            <span class="comments">&lt;!-- lets force old messages to be discarded for slow consumers --&gt;</span><span>  </span></span></li><li><span>            <span class="tag">&lt;</span><span class="tag-name">pendingMessageLimitStrategy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>              <span class="tag">&lt;</span><span class="tag-name">constantPendingMessageLimitStrategy</span><span> </span><span class="attribute">limit</span><span>=</span><span class="attribute-value">"10"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>            <span class="tag">&lt;/</span><span class="tag-name">pendingMessageLimitStrategy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    ...  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．6．5 Composite Destinations<br />   
 从1.1版本起, ActiveMQ支持composite destinations。它允许用一个虚拟的destination 
代表多个destinations。例如你可以通过composite 
destinations在一个操作中同时向12个queue发送消息。在composite 
destinations中，多个destination之间采用","分割。例如：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>Queue queue = </span><span class="keyword">new</span><span> ActiveMQQueue(</span><span class="string">"FOO.A,FOO.B,FOO.C"</span><span>);  </span></span></li></ol></div><p>   如果你希望使用不同类型的destination，那么需要加上前缀如queue:// 或topic://，例如：   </p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>Queue queue = </span><span class="keyword">new</span><span> ActiveMQQueue(</span><span class="string">"FOO.A,topic://NOTIFY.FOO.A"</span><span>);   </span></span></li></ol></div><p>   以下是ActiveMQ配置文件进行配置的一个例子： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">virtualDestinationInterceptor</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">virtualDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">compositeQueue</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"MY.QUEUE"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">forwardTo</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">queue</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"FOO"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">topic</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"BAR"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">forwardTo</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">compositeQueue</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">virtualDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">virtualDestinationInterceptor</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>   可以在转发前，先通过JMS Selector判断一个消息是否需要转发，例如：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">virtualDestinationInterceptor</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">virtualDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">compositeQueue</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"MY.QUEUE"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">forwardTo</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">filteredDestination</span><span> </span><span class="attribute">selector</span><span>=</span><span class="attribute-value">"odd = 'yes'"</span><span> </span><span class="attribute">queue</span><span>=</span><span class="attribute-value">"FOO"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">filteredDestination</span><span> </span><span class="attribute">selector</span><span>=</span><span class="attribute-value">"i = 5"</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"BAR"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">forwardTo</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">compositeQueue</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">virtualDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">virtualDestinationInterceptor</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．6．6 Mirrored Queues<br />   
 每个queue中的消息只能被一个consumer消费。然而，有时候你可能希望能够监视生产者和消费者之间的消息流。你可以通过使用Virtual 
Destinations 来建立一个virtual queue 来把消息转发到多个queues中。但是 
为系统中每个queue都进行如此的配置可能会很麻烦。 <br />    ActiveMQ支持Mirrored 
Queues。Broker会把发送到某个queue的所有消息转发到一个名称类似的topic，因此监控程序可以订阅这个mirrored queue
 topic。为了启用Mirrored 
Queues，首先要将BrokerService的useMirroredQueues属性设置成true，然后可以通过
destinationInterceptors设置其它属性，如mirror 
topic的前缀，缺省是"VirtualTopic.Mirror."。以下是ActiveMQ配置文件的一个例子： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"MirroredQueuesBroker1"</span><span> </span><span class="attribute">useMirroredQueues</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:61616"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">mirroredQueue</span><span> </span><span class="attribute">copyMessage</span><span> = </span><span class="attribute-value">"true"</span><span> </span><span class="attribute">prefix</span><span>=</span><span class="attribute-value">"Mirror.Topic"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">destinationInterceptors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  ...  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>    假如某个producer向名为Foo.Bar的queue中发送消息，那么你可以通过订阅名为Mirror.Topic.Foo.Bar的topic来获得发送到Foo.Bar中的所有消息。<img src ="http://www.blogjava.net/libin2722/aggbug/330629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:28 <a href="http://www.blogjava.net/libin2722/articles/330629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(4)</title><link>http://www.blogjava.net/libin2722/articles/330626.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330626.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330626.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330626.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330626.html</trackback:ping><description><![CDATA[
		<p>2．4 Security<br />    ActiveMQ支持可插拔的安全机制，用以在不同的provider之间切换。<br />2．4．1 Simple Authentication Plugin<br />    Simple Authentication Plugin适用于简单的认证需求，或者用于建立测试环境。它允许在XML配置文件中指定用户、用户组和密码等信息。以下是ActiveMQ配置的一个例子：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">plugins</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  ...  </span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">simpleAuthenticationPlugin</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">users</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">authenticationUser</span><span> </span><span class="attribute">username</span><span>=</span><span class="attribute-value">"system"</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">"manager"</span><span> </span><span class="attribute">groups</span><span>=</span><span class="attribute-value">"users,admins"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">authenticationUser</span><span> </span><span class="attribute">username</span><span>=</span><span class="attribute-value">"user"</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">groups</span><span>=</span><span class="attribute-value">"users"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">authenticationUser</span><span> </span><span class="attribute">username</span><span>=</span><span class="attribute-value">"guest"</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">groups</span><span>=</span><span class="attribute-value">"guests"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">users</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">simpleAuthenticationPlugin</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">plugins</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>2．4．2 JAAS Authentication Plugin<br />   
 JAAS Authentication 
Plugin依赖标准的JAAS机制来实现认证。通常情况下，你需要通过设置java.security.auth.login.config系统属性来
配置login modules的配置文件。如果没有指定这个系统属性，那么JAAS Authentication 
Plugin会缺省使用login.config作为文件名。以下是一个login.config文件的例子：</p>
		<p>activemq-domain {<br />   
 org.apache.activemq.jaas.PropertiesLoginModule required 
debug=true         
org.apache.activemq.jaas.properties.user="users.properties"         
org.apache.activemq.jaas.properties.group="groups.properties";<br />};<br />   
 
这个login.config文件中设置了两个属性：org.apache.activemq.jaas.properties.user和
org.apache.activemq.jaas.properties.group分别用来指向user.properties和
group.properties文件。需要注意的是，PropertiesLoginModule使用本地文件的查找方式，而且查找时采用的base 
directory是login.config文件所在的目录。因此这个login.config说明user.properties和
group.properties文件存放在跟login.config文件相同的目录里。<br />    以下是ActiveMQ配置的一个例子：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">plugins</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  ...  </span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">jaasAuthenticationPlugin</span><span> </span><span class="attribute">configuration</span><span>=</span><span class="attribute-value">"activemq-domain"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">plugins</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p>    基于以上的配置，在JAAS的LoginContext中会使用activemq-domain中配置的PropertiesLoginModule来进行登陆。<br />    ActiveMQ JAAS还支持LDAPLoginModule、CertificateLoginModule、TextFileCertificateLoginModule等login module。</p>
		<p> </p>
		<p>2．4．3 Custom Authentication Implementation<br />    可以通过编码的方式为ActiveMQ增加认证功能。例如编写一个类继承自XBeanBrokerService。 </p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Java代码 </div>
				</div>
				<ol class="dp-j" start="1">
						<li>
								<span>
										<span class="keyword">package</span>
										<span> com.yourpackage;  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> java.net.URI;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> java.util.HashMap;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> java.util.Map;  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> org.apache.activemq.broker.Broker;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> org.apache.activemq.broker.BrokerFactory;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> org.apache.activemq.broker.BrokerService;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> org.apache.activemq.security.SimpleAuthenticationBroker;  </span>
								</span>
						</li>
						<li>
								<span>
										<span class="keyword">import</span>
										<span> org.apache.activemq.xbean.XBeanBrokerService;  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
										<span class="keyword">public</span>
										<span> </span>
										<span class="keyword">class</span>
										<span> SimpleAuthBroker </span>
										<span class="keyword">extends</span>
										<span> XBeanBrokerService {  </span>
								</span>
						</li>
						<li>
								<span>    <span class="comment">//</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="keyword">private</span><span> String user;  </span></span>
						</li>
						<li>
								<span>    <span class="keyword">private</span><span> String password;  </span></span>
						</li>
						<li>
								<span>      </span>
						</li>
						<li>
								<span>    <span class="annotation">@SuppressWarnings</span><span>(</span><span class="string">"unchecked"</span><span>)  </span></span>
						</li>
						<li>
								<span>    <span class="keyword">protected</span><span> Broker addInterceptors(Broker broker) </span><span class="keyword">throws</span><span> Exception {  </span></span>
						</li>
						<li>
								<span>        broker = <span class="keyword">super</span><span>.addInterceptors(broker);  </span></span>
						</li>
						<li>
								<span>        Map passwords = <span class="keyword">new</span><span> HashMap();  </span></span>
						</li>
						<li>
								<span>        passwords.put(getUser(), getPassword());  </span>
						</li>
						<li>
								<span>        broker = <span class="keyword">new</span><span> SimpleAuthenticationBroker(broker, passwords, </span><span class="keyword">new</span><span> HashMap());  </span></span>
						</li>
						<li>
								<span>        <span class="keyword">return</span><span> broker;  </span></span>
						</li>
						<li>
								<span>    }  </span>
						</li>
						<li>
								<span>      </span>
						</li>
						<li>
								<span>    <span class="keyword">public</span><span> String getUser() {  </span></span>
						</li>
						<li>
								<span>        <span class="keyword">return</span><span> user;  </span></span>
						</li>
						<li>
								<span>    }  </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setUser(String user) {  </span></span>
						</li>
						<li>
								<span>        <span class="keyword">this</span><span>.user = user;  </span></span>
						</li>
						<li>
								<span>    }  </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    <span class="keyword">public</span><span> String getPassword() {  </span></span>
						</li>
						<li>
								<span>        <span class="keyword">return</span><span> password;  </span></span>
						</li>
						<li>
								<span>    }  </span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setPassword(String password) {  </span></span>
						</li>
						<li>
								<span>        <span class="keyword">this</span><span>.password = password;  </span></span>
						</li>
						<li>
								<span>    }  </span>
						</li>
						<li>
								<span>}  </span>
						</li>
				</ol>
		</div>    以下是ActiveMQ配置文件的一个例子：<div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  …  </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">auth:SimpleAuthBroker</span><span>  </span></span></li><li><span>    <span class="attribute">xmlns:auth</span><span>=</span><span class="attribute-value">"java://com.yourpackage"</span><span>  </span></span></li><li><span>    <span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"SimpleAuthBroker1"</span><span> </span><span class="attribute">user</span><span>=</span><span class="attribute-value">"user"</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    </span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:61616"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">auth:SimpleAuthBroker</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  …  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>  
 在这个配置文件中增加了一个namespace 
auth，用于指向之前编写的哪个类。同时为SimpleAuthBroker注入了两个属性值user和password，因此在被
SimpleAuthBroker改写的addInterceptors方法里，可以使用这两个属性进行认证了。ActiveMQ提供的
SimpleAuthenticationBroker类继承自BrokerFilter（可以简单的看成是Broker的Adaptor），它的构造函
数中的两个Map分别是userPasswords和userGroups。 SimpleAuthenticationBroker在 
addConnection方法中使用userPasswords进行认证，同时会把userGroups的信息保存到
ConnectionContext中 。</p><p> </p><p>2．4．4 Authorization Plugin<br />    可以通过Authorization Plugin为认证后的用户授权，以下ActiveMQ配置文件的一个例子：</p><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">plugins</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">jaasAuthenticationPlugin</span><span> </span><span class="attribute">configuration</span><span>=</span><span class="attribute-value">"activemq-domain"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">authorizationPlugin</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">map</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">authorizationMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;</span><span class="tag-name">authorizationEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">queue</span><span>=</span><span class="attribute-value">"&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">queue</span><span>=</span><span class="attribute-value">"USERS.&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">queue</span><span>=</span><span class="attribute-value">"GUEST.&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"guests"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>            </span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"admins"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"USERS.&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"users"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"GUEST.&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"guests"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  </span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">authorizationEntry</span><span> </span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"ActiveMQ.Advisory.&gt;"</span><span> </span><span class="attribute">read</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="attribute">write</span><span>=</span><span class="attribute-value">"guests,users"</span><span> </span><span class="attribute">admin</span><span>=</span><span class="attribute-value">"guests,users"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>        <span class="tag">&lt;/</span><span class="tag-name">authorizationEntries</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">authorizationMap</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">map</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">authorizationPlugin</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">plugins</span><span class="tag">&gt;</span><span></span></span></li></ol><img src ="http://www.blogjava.net/libin2722/aggbug/330626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:27 <a href="http://www.blogjava.net/libin2722/articles/330626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(5)</title><link>http://www.blogjava.net/libin2722/articles/330627.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330627.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330627.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330627.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330627.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330627.html</trackback:ping><description><![CDATA[
		<p>2．5 Clustering<br />    ActiveMQ从多种不同的方面提供了集群的支持。<br />2．5．1 Queue consumer clusters<br />   
 
ActiveMQ支持订阅同一个queue的consumers上的集群。如果一个consumer失效，那么所有未被确认
（unacknowledged）的消息都会被发送到这个queue上其它的consumers。如果某个consumer的处理速度比其它
consumers更快，那么这个consumer就会消费更多的消息。<br />    需要注意的是，笔者发现AcitveMQ5.0版本的Queue consumer clusters存在一个bug：采用AMQ Message Store，运行一个producer，两个consumer，并采用如下的配置文件：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">beans</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"BugBroker1"</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    </span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:61616"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      </span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">amqPersistenceAdapter</span><span> </span><span class="attribute">directory</span><span>=</span><span class="attribute-value">"activemq-data/BugBroker1"</span><span> </span><span class="attribute">maxFileLength</span><span>=</span><span class="attribute-value">"32mb"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>       </span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">beans</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p>   那么经过一段时间后可能会报出如下错误：<br />ERROR
 [ActiveMQ Transport: tcp:///127.0.0.1:1843 - 
RecoveryListenerAdapter.java:58 - RecoveryListenerAdapter] Message id 
ID:versus-1837-1203915536609-0:2:1:1:419 could not be recovered from the
 data store!<br />    Apache官方文档说，此bug已经被修正，预定在5.1.0版本上体现。</p>
		<p> </p>
		<p>2．5．2 Broker clusters<br />   
 一个常见的场景是有多个JMS 
broker，有一个客户连接到其中一个broker。如果这个broker失效，那么客户会自动重新连接到其它的broker。在ActiveMQ中使
用failover:// 协议来实现这个功能。ActiveMQ3.x版本的reliable://协议已经变更为failover://。<br />   
 如果某个网络上有多个brokers而且客户使用静态发现（使用Static Transport或Failover 
Transport）或动态发现（使用Discovery 
Transport），那么客户可以容易地在某个broker失效的情况下切换到其它的brokers。然而，stand alone 
brokers并不了解其它brokers上的consumers，也就是说如果某个broker上没有consumers，那么这个broker上的消
息可能会因得不到处理而积压起来。目前的解决方案是使用Network of 
brokers，以便在broker之间存储转发消息。ActiveMQ在未来会有更好的特性，用来在客户端处理这个问题。<br />    
从ActiveMQ1.1版本起，ActiveMQ支持networks of 
brokers。它支持分布式的queues和topics。一个broker会相同对待所有的订阅（subscription）：不管他们是来自本地的
客户连接，还是来自远程broker，它都会递送有关的消息拷贝到每个订阅。远程broker得到这个消息拷贝后，会依次把它递送到其内部的本地连接上。
有两种方式配置Network of brokers，一种是使用static transport，如下：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">broker</span>
										<span> </span>
										<span class="attribute">brokerName</span>
										<span>=</span>
										<span class="attribute-value">"receiver"</span>
										<span> </span>
										<span class="attribute">persistent</span>
										<span>=</span>
										<span class="attribute-value">"false"</span>
										<span> </span>
										<span class="attribute">useJmx</span>
										<span>=</span>
										<span class="attribute-value">"false"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:62002"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;</span><span class="tag-name">networkConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"static:( tcp://localhost:61616,tcp://remotehost:61616)"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  …  </span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">broker</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>    另外一种是使用multicast discovery，如下：<div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"sender"</span><span> </span><span class="attribute">persistent</span><span>=</span><span class="attribute-value">"false"</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:0"</span><span> </span><span class="attribute">discoveryUri</span><span>=</span><span class="attribute-value">"multicast://default"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">networkConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"multicast://default"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  ...  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>    Network Connector有以下属性：<br /><table border="2"><tbody><tr><td><strong>Property</strong></td><td><strong>Default Value</strong></td><td><strong>Description</strong></td></tr><tr><td>name</td><td>bridge</td><td>name of the network - for more than one network connector between the same two brokers - use different names</td></tr><tr><td>dynamicOnly</td><td>false</td><td>if true, only forward messages if a consumer is active on the connected broker</td></tr><tr><td>decreaseNetworkConsumerPriority</td><td>false</td><td>decrease the priority for dispatching to a Queue consumer the further away it is (in network hops) from the producer</td></tr><tr><td>networkTTL</td><td>1</td><td>the number of brokers in the network that messages and subscriptions can pass through</td></tr><tr><td>conduitSubscriptions</td><td>true</td><td>multiple consumers subscribing to the same destination are treated as one consumer by the network</td></tr><tr><td>excludedDestinations</td><td>empty</td><td>destinations matching this list won't be forwarded across the network</td></tr><tr><td>dynamicallyIncludedDestinations</td><td>empty</td><td>destinations
 that match this list will be forwarded across the network n.b. an empty
 list means all destinations not in the excluded list will be forwarded</td></tr><tr><td>staticallyIncludedDestinations</td><td>empty</td><td>destinations that match will always be passed across the network - even if no consumers have ever registered an interest</td></tr><tr><td>duplex</td><td>false</td><td>if
 true, a network connection will be used to both produce AND Consume 
messages. This is useful for hub and spoke scenarios when the hub is 
behind a firewall etc.<br /><br /></td></tr></tbody></table><p>    
关于conduitSubscriptions属性，这里稍稍说明一下。设想有两个brokers，分别是brokerA和brokerB，它们之间用
forwarding 
bridge连接。有一个consumer连接到brokerA并订阅queue：Q.TEST。有两个consumers连接到brokerB，也是订
阅queue：Q.TEST。这三个consumers有相同的优先级。然后启动一个producer，它发送了30条消息到brokerA。如果
conduitSubscriptions=true，那么brokerA上的consumer会得到15条消息， 
另外15条消息会发送给brokerB。此时负载并不均衡，因为此时brokerA将brokerB上的两个consumers视为一个；如果
conduitSubscriptions=false，那么每个consumer上都会收到10条消息。以下是关于NetworkConnector属
性的一个例子：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">networkConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"static://(tcp://localhost:61617)"</span><span>  </span></span></li><li><span>     <span class="attribute">name</span><span>=</span><span class="attribute-value">"bridge"</span><span> </span><span class="attribute">dynamicOnly</span><span>=</span><span class="attribute-value">"false"</span><span> </span><span class="attribute">conduitSubscriptions</span><span>=</span><span class="attribute-value">"true"</span><span>  </span></span></li><li><span>     <span class="attribute">decreaseNetworkConsumerPriority</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">excludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">queue</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"exclude.test.foo"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">topic</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"exclude.test.bar"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;/</span><span class="tag-name">excludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">dynamicallyIncludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">queue</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"include.test.foo"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">topic</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"include.test.bar"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;/</span><span class="tag-name">dynamicallyIncludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">staticallyIncludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">queue</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"always.include.queue"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>       <span class="tag">&lt;</span><span class="tag-name">topic</span><span> </span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"always.include.topic"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;/</span><span class="tag-name">staticallyIncludedDestinations</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">networkConnector</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">networkConnectors</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．5．3 Master Slave<br />   
 在一个网络内运行多个brokers或者stand alone 
brokers时存在一个问题，这就是消息在物理上只被一个broker持有，因此当某个broker失效，那么你只能等待直到它重启后，这个
broker上的消息才能够被继续发送（如果没有设置持久化，那么在这种情况下，消息将会丢失）。Master Slave 
背后的想法是，消息被复制到slave broker，因此即使master broker遇到了像硬件故障之类的错误，你也可以立即切换到slave 
broker而不丢失任何消息。<br />    Master Slave是目前ActiveMQ推荐的高可靠性和容错的解决方案。以下是几种不同的类型： </p><table border="2"><tbody><tr><td><strong>Master Slave Type</strong></td><td><strong>Requirements</strong></td><td><strong>Pros</strong></td><td><strong>Cons</strong></td></tr><tr><td>Pure Master Slave</td><td>None</td><td>No central point of failure</td><td>Requires manual restart to bring back a failed master and can only support 1 slave</td></tr><tr><td>Shared File System Master Slave</td><td>A Shared File system such as a SAN</td><td>Run as many slaves as required. Automatic recovery of old masters</td><td>Requires shared file system</td></tr><tr><td>JDBC Master Slave</td><td>A Shared database</td><td>Run as many slaves as required. Automatic recovery of old masters</td><td>Requires a shared database. Also relatively slow as it cannot use the high performance journal</td></tr></tbody></table><p> </p><p>2．5．3．1 Pure Master Slave<br />    Pure Master Slave的工作方式如下：</p><ul><li>Slave
 broker消费master broker上所有的消息状态，例如消息、确认和事务状态等。只要slave broker连接到了master 
broker，它不会（也不被允许）启动任何network connectors或者transport 
connectors，所以唯一的目的就是复制master broker的状态。</li><li>Master broker只有在消息成功被复制到slave broker之后才会响应客户。例如，客户的commit请求只有在master broker和slave broker都处理完毕commit请求之后才会结束。</li><li>当master
 broker失效的时候，slave broker有两种选择，一种是slave broker启动所有的network 
connectors和transport connectors，这允许客户端切换到slave broker；另外一种是slave 
broker停止。这种情况下，slave broker只是复制了master broker的状态。</li><li>客户应该使用failover transport并且应该首先尝试连接master broker。例如：<br />failover://(tcp://masterhost:61616,tcp://slavehost:61616)?randomize=false<br />设置randomize为false就可以让客户总是首先尝试连接master broker（slave broker并不会接受任何连接，直到它成为了master broker）。</li></ul><p>   Pure Master Slave具有以下限制：</p><ul><li>只能有一个slave broker连接到master broker。</li><li>在因master broker失效而导致slave broker成为master之后，之前的master broker只有在当前的master broker（原slave broker）停止后才能重新生效。</li><li>Master
 broker失效后而切换到slave broker后，最安全的恢复master broker的方式是人工处理。首先要停止slave 
broker（这意味着所有的客户也要停止）。然后把slave broker的数据目录中所有的数据拷贝到master 
broker的数据目录中。然后重启master broker和slave broker。</li></ul><p>   Master broker不需要特殊的配置。Slave broker需要进行以下配置</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">masterConnectorURI</span><span>=</span><span class="attribute-value">"tcp://masterhost:62001"</span><span> </span><span class="attribute">shutdownOnMasterFailure</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    ...  </span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://slavehost:61616"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>   <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>    其中的masterConnectorURI用于指向master broker，shutdownOnMasterFailure用于指定slave broker在master broker失效的时候是否需要停止。此外，也可以使用如下配置：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"slave"</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"false"</span><span>  </span><span class="attribute">deleteAllMessagesOnStartup</span><span>=</span><span class="attribute-value">"true"</span><span>  </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  ...  </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">services</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">masterConnector</span><span> </span><span class="attribute">remoteURI</span><span>= </span><span class="attribute-value">"tcp://localhost:62001"</span><span> </span><span class="attribute">userName</span><span>=</span><span class="attribute-value">"user"</span><span> </span><span class="attribute">password</span><span>=</span><span class="attribute-value">"password"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">services</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>   需要注意的是，笔者认为ActiveMQ5.0版本的Pure Master Slave仍然不够稳定。 </p><p> </p><p>2．5．3．2 Shared File System Master Slave<br />   
 如果你使用SAN或者共享文件系统，那么你可以使用Shared File System Master 
Slave。基本上，你可以运行多个broker，这些broker共享数据目录。当第一个broker得到文件上的排他锁之后，其它的broker便会
在循环中等待获得这把锁。客户端使用failover transport来连接到可用的broker。当master 
broker失效的时候会释放这把锁，这时候其中一个slave broker会得到这把锁从而成为master 
broker。以下是ActiveMQ配置的一个例子：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"false"</span><span>  </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>   <span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">journaledJDBC</span><span> </span><span class="attribute">dataDirectory</span><span>=</span><span class="attribute-value">"/sharedFileSystem/broker"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>   <span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>   …  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．5．3．3 JDBC Master Slave<br />    JDBC Master Slave的工作原理跟Shared File System Master Slave类似，只是采用了数据库作为持久化存储。以下是ActiveMQ配置的一个例子： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"JdbcMasterBroker"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    ...  </span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">jdbcPersistenceAdapter</span><span> </span><span class="attribute">dataSource</span><span>=</span><span class="attribute-value">"#mysql-ds"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      </span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    </span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"mysql-ds"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.apache.commons.dbcp.BasicDataSource"</span><span> </span><span class="attribute">destroy-method</span><span>=</span><span class="attribute-value">"close"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"driverClassName"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"com.mysql.jdbc.Driver"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"url"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"jdbc:mysql://localhost:3306/test?relaxAutoCommit=true"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"username"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"username"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"passward"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"poolPreparedStatements"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>   </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>   需要注意的是，如果你使用MySQL数据库，需要首先执行以下三条语句：（Apache官方文档说，此bug已经被修正，预定在5.1.0版本上体现） </p><div class="bar"><div class="tools">Sql代码 </div></div><ol class="dp-sql" start="1"><li><span><span class="keyword">ALTER</span><span> </span><span class="keyword">TABLE</span><span> activemq_acks ENGINE = InnoDB;  </span></span></li><li><span><span class="keyword">ALTER</span><span> </span><span class="keyword">TABLE</span><span> activemq_lock ENGINE = InnoDB;  </span></span></li><li><span><span class="keyword">ALTER</span><span> </span><span class="keyword">TABLE</span><span> activemq_msgs ENGINE = InnoDB; <br /></span></span></li></ol><img src ="http://www.blogjava.net/libin2722/aggbug/330627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:27 <a href="http://www.blogjava.net/libin2722/articles/330627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(3)</title><link>http://www.blogjava.net/libin2722/articles/330625.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330625.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330625.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330625.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330625.html</trackback:ping><description><![CDATA[
		<p>2．3 Persistence<br />2．3．1 AMQ Message Store<br />    AMQ Message Store是ActiveMQ<span style="font-size: 10.5pt; font-family: 'Times New Roman';">5.0</span>缺
省的持久化存储。Message commands被保存到transactional journal（由rolling data 
logs组成）。Messages被保存到data logs中，同时被reference store进行索引以提高存取速度。Date 
logs由一些单独的data log文件组成，缺省的文件大小是32M，如果某个消息的大小超过了data 
log文件的大小，那么可以修改配置以增加data log文件的大小。如果某个data log文件中所有的消息都被成功消费了，那么这个data 
log文件将会被标记，以便在下一轮的清理中被删除或者归档。以下是其配置的一个例子：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">broker</span>
										<span> </span>
										<span class="attribute">brokerName</span>
										<span>=</span>
										<span class="attribute-value">"broker"</span>
										<span> </span>
										<span class="attribute">persistent</span>
										<span>=</span>
										<span class="attribute-value">"true"</span>
										<span> </span>
										<span class="attribute">useShutdownHook</span>
										<span>=</span>
										<span class="attribute-value">"false"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>     <span class="tag">&lt;</span><span class="tag-name">amqPersistenceAdapter</span><span> </span><span class="attribute">directory</span><span>=</span><span class="attribute-value">"${activemq.base}/data"</span><span> </span><span class="attribute">maxFileLength</span><span>=</span><span class="attribute-value">"32mb"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">broker</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Property name</strong>
								</td>
								<td>
										<strong>Default value</strong>
								</td>
								<td>
										<strong>Comments</strong>
								</td>
						</tr>
						<tr>
								<td>directory</td>
								<td>activemq-data</td>
								<td>the path to the directory to use to store the message store data and log files</td>
						</tr>
						<tr>
								<td>useNIO</td>
								<td>true</td>
								<td>use NIO to write messages to the data logs</td>
						</tr>
						<tr>
								<td>syncOnWrite</td>
								<td>false</td>
								<td>sync every write to disk</td>
						</tr>
						<tr>
								<td>maxFileLength</td>
								<td>32mb</td>
								<td>a hint to set the maximum size of the message data logs</td>
						</tr>
						<tr>
								<td>persistentIndex</td>
								<td>true</td>
								<td>use a persistent index for the message logs. If this is false, an in-memory structure is maintained</td>
						</tr>
						<tr>
								<td>maxCheckpointMessageAddSize</td>
								<td>4kb</td>
								<td>the maximum number of messages to keep in a transaction before automatically committing</td>
						</tr>
						<tr>
								<td>cleanupInterval</td>
								<td>30000</td>
								<td>time (ms) before checking for a discarding/moving message data logs that are no longer used</td>
						</tr>
						<tr>
								<td>indexBinSize</td>
								<td>1024</td>
								<td>default number of bins used by the index. The bigger the bin size - the better the relative performance of the index</td>
						</tr>
						<tr>
								<td>indexKeySize</td>
								<td>96</td>
								<td>the size of the index key - the key is the message id</td>
						</tr>
						<tr>
								<td>indexPageSize</td>
								<td>16kb</td>
								<td>the size of the index page - the bigger the page - the better the write performance of the index</td>
						</tr>
						<tr>
								<td>directoryArchive</td>
								<td>archive</td>
								<td>the path to the directory to use to store discarded data logs</td>
						</tr>
						<tr>
								<td>archiveDataLogs</td>
								<td>false</td>
								<td>if true data logs are moved to the archive directory instead of being deleted</td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<p>2．3．2 Kaha Persistence<br />    Kaha Persistence 是一个专门针对消息持久化的解决方案。它对典型的消息使用模式进行了优化。在Kaha中，数据被追加到data logs中。当不再需要log文件中的数据的时候，log文件会被丢弃。以下是其配置的一个例子： </p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">broker</span>
										<span> </span>
										<span class="attribute">brokerName</span>
										<span>=</span>
										<span class="attribute-value">"broker"</span>
										<span> </span>
										<span class="attribute">persistent</span>
										<span>=</span>
										<span class="attribute-value">"true"</span>
										<span> </span>
										<span class="attribute">useShutdownHook</span>
										<span>=</span>
										<span class="attribute-value">"false"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>        <span class="tag">&lt;</span><span class="tag-name">kahaPersistenceAdapter</span><span> </span><span class="attribute">directory</span><span>=</span><span class="attribute-value">"activemq-data"</span><span> </span><span class="attribute">maxDataFileLength</span><span>=</span><span class="attribute-value">"33554432"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">broker</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p> </p>
		<p>2．3．3 JDBC Persistence<br />    目前支持的数据库有Apache Derby, Axion, DB2, HSQL, Informix, MaxDB, MySQL, Oracle, Postgresql, SQLServer, Sybase。<br />    如果你使用的数据库不被支持，那么可以调整StatementProvider 来保证使用正确的SQL方言（flavour of SQL）。通常绝大多数数据库支持以下adaptor： </p>
		<ul>
				<li>org.activemq.store.jdbc.adapter.BlobJDBCAdapter</li>
				<li>org.activemq.store.jdbc.adapter.BytesJDBCAdapter</li>
				<li>org.activemq.store.jdbc.adapter.DefaultJDBCAdapter</li>
				<li>org.activemq.store.jdbc.adapter.ImageJDBCAdapter</li>
		</ul>
		<p>   也可以在配置文件中直接指定JDBC adaptor，例如：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">jdbcPersistenceAdapter</span>
										<span>  </span>
										<span class="attribute">adapterClass</span>
										<span>=</span>
										<span class="attribute-value">"org.apache.activemq.store.jdbc.adapter.ImageBasedJDBCAdaptor"</span>
										<span class="tag">/&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>     以下是其配置的一个例子：<br /><p> </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">persistence</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">jdbcPersistence</span><span> </span><span class="attribute">dataSourceRef</span><span>=</span><span class="attribute-value">" mysql-ds"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">persistence</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  </span></li><li><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"mysql-ds"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.apache.commons.dbcp.BasicDataSource"</span><span> </span><span class="attribute">destroy-method</span><span>=</span><span class="attribute-value">"close"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"driverClassName"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"com.mysql.jdbc.Driver"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"url"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"jdbc:mysql://localhost/activemq?relaxAutoCommit=true"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"username"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"activemq"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"password"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"activemq"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"poolPreparedStatements"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>     需要注意的是，如果使用MySQL，那么需要设置relaxAutoCommit 标志为true。</p><p> </p><p>2．3．4 Disable Persistence<br />    以下是其配置的一个例子： </p><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">persistent</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span></span></span></li></ol><img src ="http://www.blogjava.net/libin2722/aggbug/330625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:26 <a href="http://www.blogjava.net/libin2722/articles/330625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(2)</title><link>http://www.blogjava.net/libin2722/articles/330624.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:26:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330624.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330624.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330624.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330624.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330624.html</trackback:ping><description><![CDATA[
		<p>2．2 Transport<br />    ActiveMQ目前支持的transport有：VM Transport、TCP 
Transport、SSL Transport、Peer Transport、UDP Transport、Multicast 
Transport、HTTP and HTTPS Transport、Failover Transport、Fanout 
Transport、Discovery Transport、ZeroConf 
Transport等。以下简单介绍其中的几种，更多请参考Apache官方文档。</p>
		<p> </p>
		<p>2．2．1 VM Transport<br />   
 VM transport允许在VM内部通信，从而避免了网络传输的开销。这时候采用的连接不是socket连接，而是直接地方法调用。 
第一个创建VM 连接的客户会启动一个embed VM broker，接下来所有使用相同的broker 
name的VM连接都会使用这个broker。当这个broker上所有的连接都关闭的时候，这个broker也会自动关闭。<br />    以下是配置语法： </p>
		<p>   vm://brokerName?transportOptions</p>
		<p>   例如：vm://broker1?marshal=false&amp;broker.persistent=false</p>
		<p>   Transport Options的可选值如下： </p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Option Name</strong>
								</td>
								<td>
										<strong>Default Value</strong>
								</td>
								<td>
										<strong>Description</strong>
								</td>
						</tr>
						<tr>
								<td>Marshal</td>
								<td>false</td>
								<td>If true, forces each command sent over the transport to be marshlled and unmarshlled using a WireFormat</td>
						</tr>
						<tr>
								<td>wireFormat</td>
								<td>default</td>
								<td>The name of the WireFormat to use</td>
						</tr>
						<tr>
								<td>wireFormat.*</td>
								<td> </td>
								<td>All the properties with this prefix are used to configure the wireFormat</td>
						</tr>
						<tr>
								<td>create</td>
								<td>true</td>
								<td>If the broker should be created on demand if it does not allready exist. Only supported in ActiveMQ 4.1</td>
						</tr>
						<tr>
								<td>broker.*</td>
								<td> </td>
								<td>All the properties with this prefix are used to configure the broker. See Configuring Wire Formats for more information</td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<p>   以下是高级配置语法：</p>
		<p>   vm:(broker:(tcp://localhost)?brokerOptions)?transportOptions</p>
		<p>   vm:broker:(tcp://localhost)?brokerOptions</p>
		<p>    例如：vm:(broker:(tcp://localhost:6000)?persistent=false)?marshal=false</p>
		<p>     Transport Options的可选值如下：</p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Option Name</strong>
								</td>
								<td>
										<strong>Default Value</strong>
								</td>
								<td>
										<strong>Description</strong>
								</td>
						</tr>
						<tr>
								<td>marshal</td>
								<td>false</td>
								<td>If true, forces each command sent over the transport to be marshlled and unmarshlled using a WireFormat</td>
						</tr>
						<tr>
								<td>wireFormat</td>
								<td>default</td>
								<td>The name of the WireFormat to use</td>
						</tr>
						<tr>
								<td>wireFormat.*</td>
								<td> </td>
								<td>All the properties with this prefix are used to configure the wireFormat</td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<p>   使用配置文件的配置语法：    <br />    vm://localhost?brokerConfig=xbean:activemq.xml<br />    例如：vm:// localhost?brokerConfig=xbean:com/test/activemq.xml</p>
		<p> </p>
		<p>   使用Spring的配置：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">bean</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"broker"</span>
										<span> </span>
										<span class="attribute">class</span>
										<span>=</span>
										<span class="attribute-value">"org.apache.activemq.xbean.BrokerFactoryBean"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"config"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"classpath:org/apache/activemq/xbean/activemq.xml"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"start"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">bean</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  </span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">bean</span>
										<span> </span>
										<span class="attribute">id</span>
										<span>=</span>
										<span class="attribute-value">"connectionFactory"</span>
										<span> </span>
										<span class="attribute">class</span>
										<span>=</span>
										<span class="attribute-value">"org.apache.activemq.ActiveMQConnectionFactory"</span>
										<span> </span>
										<span class="attribute">depends-on</span>
										<span>=</span>
										<span class="attribute-value">"broker"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>  <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"brokerURL"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"vm://localhost"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">bean</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p>  
 
如果persistent是true，那么ActiveMQ会在当前目录下创建一个缺省值是activemq-data的目录用于持久化保存数据。需要注
意的是，如果程序中启动了多个不同名字的VM broker，那么可能会有如下警告：Failed to start jmx connector: 
Cannot bind to URL [rmi://localhost:1099/jmxrmi]: 
javax.naming.NameAlreadyBoundException…可以通过在transportOptions中追加
broker.useJmx=false来禁用JMX来避免这个警告。</p>
		<p> </p>
		<p>2．2．2 TCP Transport<br />    TCP transport 允许客户端通过TCP socket连接到远程的broker。以下是配置语法：<br />    tcp://hostname:port?transportOptions<br />    Transport Options的可选值如下：</p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Option Name</strong>
								</td>
								<td>
										<strong>Default Value</strong>
								</td>
								<td>
										<strong>Description</strong>
								</td>
						</tr>
						<tr>
								<td>minmumWireFormatVersion</td>
								<td>0</td>
								<td>The minimum version wireformat that is allowed</td>
						</tr>
						<tr>
								<td>trace</td>
								<td>false</td>
								<td>Causes all commands that are sent over the transport to be logged</td>
						</tr>
						<tr>
								<td>useLocalHost</td>
								<td>true</td>
								<td>When true, it causes the local machines name to resolve to "localhost".</td>
						</tr>
						<tr>
								<td>socketBufferSize</td>
								<td>64 * 1024</td>
								<td>Sets the socket buffer size in bytes</td>
						</tr>
						<tr>
								<td>soTimeout</td>
								<td>0</td>
								<td>sets the socket timeout in milliseconds</td>
						</tr>
						<tr>
								<td>connectionTimeout</td>
								<td>30000</td>
								<td>A
 non-zero value specifies the connection timeout in milliseconds. A zero
 value means wait forever for the connection to be established. Negative
 values are ignored.</td>
						</tr>
						<tr>
								<td>wireFormat</td>
								<td>default</td>
								<td>The name of the WireFormat to use</td>
						</tr>
						<tr>
								<td>wireFormat.*</td>
								<td> </td>
								<td>All the properties with this prefix are used to configure the wireFormat. See Configuring Wire Formats for more information</td>
						</tr>
				</tbody>
		</table>
		<p>   例如：tcp://localhost:61616?trace=false </p>
		<p> </p>
		<p>2．2．3 Failover Transport<br />   
 Failover 
Transport是一种重新连接的机制，它工作于其它transport的上层，用于建立可靠的传输。它的配置语法允许制定任意多个复合的URI。
Failover 
transport会自动选择其中的一个URI来尝试建立连接。如果没有成功，那么会选择一个其它的URI来建立一个新的连接。以下是配置语法：<br />    failover:(uri1,...,uriN)?transportOptions<br />    failover:uri1,...,uriN<br />    Transport Options的可选值如下： </p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Option Name</strong>
								</td>
								<td>
										<strong>D</strong>
										<strong>efault Value</strong>
								</td>
								<td>
										<strong>Description</strong>
								</td>
						</tr>
						<tr>
								<td>initialReconnectDelay</td>
								<td>10</td>
								<td>How long to wait before the first reconnect attempt (in ms)</td>
						</tr>
						<tr>
								<td>maxReconnectDelay</td>
								<td>30000</td>
								<td>The maximum amount of time we ever wait between reconnect attempts (in ms)</td>
						</tr>
						<tr>
								<td>useExponentialBackOff</td>
								<td>true</td>
								<td>Should an exponential backoff be used between reconnect attempts</td>
						</tr>
						<tr>
								<td>backOffMultiplier</td>
								<td>2</td>
								<td>The exponent used in the exponential backoff attempts</td>
						</tr>
						<tr>
								<td>maxReconnectAttempts</td>
								<td>0</td>
								<td>If not 0, then this is the maximum number of reconnect attempts before an error is sent back to the client</td>
						</tr>
						<tr>
								<td>randomize</td>
								<td>true</td>
								<td>use a random algorithm to choose the URI to use for reconnect from the list provided</td>
						</tr>
						<tr>
								<td>backup</td>
								<td>false</td>
								<td>initialize and hold a second transport connection - to enable fast failover</td>
						</tr>
				</tbody>
		</table>
		<p>   例如：failover:(tcp://localhost:61616,tcp://remotehost:61616)?initialReconnectDelay=100</p>
		<p> </p>
		<p>2．2．4 Discovery transport<br />    Discovery transport是可靠的tranport。它使用Discovery transport来定位用来连接的URI列表。以下是配置语法：<br />    discovery:(discoveryAgentURI)?transportOptions<br />    discovery:discoveryAgentURI<br />    Transport Options的可选值如下： </p>
		<table border="2">
				<tbody>
						<tr>
								<td>
										<strong>Option Name</strong>
								</td>
								<td>
										<strong>Default Value</strong>
								</td>
								<td>
										<strong>Description</strong>
								</td>
						</tr>
						<tr>
								<td>initialReconnectDelay</td>
								<td>10</td>
								<td>How long to wait before the first reconnect attempt</td>
						</tr>
						<tr>
								<td>maxReconnectDelay</td>
								<td>30000</td>
								<td>The maximum amount of time we ever wait between reconnect attempts</td>
						</tr>
						<tr>
								<td>useExponentialBackOff</td>
								<td>true</td>
								<td>Should an exponential backoff be used btween reconnect attempts</td>
						</tr>
						<tr>
								<td>backOffMultiplier</td>
								<td>2</td>
								<td>The exponent used in the exponential backoff attempts</td>
						</tr>
						<tr>
								<td>maxReconnectAttempts</td>
								<td>0</td>
								<td>If not 0, then this is the maximum number of reconnect attempts before an error is sent back to the client</td>
						</tr>
				</tbody>
		</table>
		<p>   例如：discovery:(multicast://default)?initialReconnectDelay=100    <br />    为了使用Discovery来发现broker，需要为broker启用discovery agent。 以下是XML配置文件中的一个例子：</p>
		<div class="dp-highlighter">
				<div class="bar">
						<div class="tools">Xml代码 </div>
				</div>
				<ol class="dp-xml" start="1">
						<li>
								<span>
										<span class="tag">&lt;</span>
										<span class="tag-name">broker</span>
										<span> </span>
										<span class="attribute">name</span>
										<span>=</span>
										<span class="attribute-value">"foo"</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
						<li>
								<span>   <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>      <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:0"</span><span> </span><span class="attribute">discoveryUri</span><span>=</span><span class="attribute-value">"multicast://default"</span><span class="tag">/&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span>
						</li>
						<li>
								<span>    ...  </span>
						</li>
						<li>
								<span>
										<span class="tag">&lt;/</span>
										<span class="tag-name">broker</span>
										<span class="tag">&gt;</span>
										<span>  </span>
								</span>
						</li>
				</ol>
		</div>
		<p>  
 在使用Failover Transport或Discovery 
transport等能够自动重连的transport的时候，需要注意的是：设想有两个broker，它们都启用AMQ Message 
Store作为持久化存储，有一个producer和一个consumer连接到某个queue。当因其中一个broker失效时而切换到另一个
broker的时候，如果失效的broker的queue中还有未被consumer消费的消息，那么这个queue里的消息仍然滞留在失效broker
的中，直到失效的broker被修复并重新切换回这个被修复的broker后，之前被保留的消息才会被consumer消费掉。如果被处理的消息有时序限
制，那么应用程序就需要处理这个问题。另外也可以通过ActiveMQ集群来解决这个问题。</p>
		<p>   在transport重连的时候，可以在connection上注册TransportListener来获得回调，例如：</p>
		<div class="bar">
				<div class="tools">Java代码 </div>
		</div>
		<ol class="dp-j" start="1">
				<li>
						<span>
								<span>(ActiveMQConnection)connection).addTransportListener(</span>
								<span class="keyword">new</span>
								<span> TransportListener() {  </span>
						</span>
				</li>
				<li>
						<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onCommand(Object cmd) {  </span></span>
				</li>
				<li>
						<span>    }  </span>
				</li>
				<li>
						<span>  </span>
				</li>
				<li>
						<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onException(IOException exp) {  </span></span>
				</li>
				<li>
						<span>    }  </span>
				</li>
				<li>
						<span>  </span>
				</li>
				<li>
						<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> transportInterupted() {  </span></span>
				</li>
				<li>
						<span>        <span class="comment">// The transport has suffered an interruption from which it hopes to recover.</span><span>  </span></span>
				</li>
				<li>
						<span>    }  </span>
				</li>
				<li>
						<span>  </span>
				</li>
				<li>
						<span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> transportResumed() {  </span></span>
				</li>
				<li>
						<span>        <span class="comment">// The transport has resumed after an interruption.</span><span>  </span></span>
				</li>
				<li>
						<span>    }  </span>
				</li>
				<li>
						<span>}); <br /></span>
				</li>
		</ol>
<img src ="http://www.blogjava.net/libin2722/aggbug/330624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:26 <a href="http://www.blogjava.net/libin2722/articles/330624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ in Action(1)</title><link>http://www.blogjava.net/libin2722/articles/330623.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:25:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330623.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330623.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330623.html</trackback:ping><description><![CDATA[
		<div class="blog_content">
				<p>1 JMS<br />    在介绍ActiveMQ之前，首先简要介绍一下JMS规范。<br />1．1 JMS的基本构件<br />1．1．1 连接工厂<br />    连接工厂是客户用来创建连接的对象，例如ActiveMQ提供的ActiveMQConnectionFactory。</p>
				<p>
						<br />1．1．2 连接<br />    JMS Connection封装了客户与JMS提供者之间的一个虚拟的连接。</p>
				<p>
						<br />1．1．3 会话<br />    JMS Session是生产和消费消息的一个单线程上下文。会话用于创建消息生产者（producer）、消息消费者（consumer）和消息（message）等。会话提供了一个事务性的上下文，在这个上下文中，一组发送和接收被组合到了一个原子操作中。</p>
				<p>
						<br />1．1．4 目的地<br />    目的地是客户用来指定它生产的消息的目标和它消费的消息的来源的对象。JMS<span style="font-size: 10.5pt; font-family: 'Times New Roman';">1.0.2</span>规范中定义了两种消息传递域：点对点（PTP）消息传递域和发布/订阅消息传递域。<br />点对点消息传递域的特点如下：</p>
				<ul>
						<li>每个消息只能有一个消费者。</li>
						<li>消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态，它都可以提取消息。</li>
				</ul>
				<p>   发布/订阅消息传递域的特点如下：</p>
				<ul>
						<li>每个消息可以有多个消费者。</li>
						<li>生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消费自它订阅之后发布的消息。JMS规范允许客户创建持久订阅，这在一定程度上放松了时间上的相关性要求。持久订阅允许消费者消费它在未处于激活状态时发送的消息。</li>
				</ul>
				<p>  在点对点消息传递域中，目的地被成为队列（queue）；在发布/订阅消息传递域中，目的地被成为主题（topic）。</p>
				<p> </p>
				<p>1．1．5 消息生产者<br />    消息生产者是由会话创建的一个对象，用于把消息发送到一个目的地。</p>
				<p>
						<br />1．1．6 消息消费者<br />    消息消费者是由会话创建的一个对象，它用于接收发送到目的地的消息。消息的消费可以采用以下两种方法之一：</p>
				<ul>
						<li>同步消费。通过调用消费者的receive方法从目的地中显式提取消息。receive方法可以一直阻塞到消息到达。</li>
						<li>异步消费。客户可以为消费者注册一个消息监听器，以定义在消息到达时所采取的动作。</li>
				</ul>
				<p>1．1．7 消息<br />    JMS消息由以下三部分组成：</p>
				<ul>
						<li>消息头。每个消息头字段都有相应的getter和setter方法。</li>
						<li>消息属性。如果需要除消息头字段以外的值，那么可以使用消息属性。</li>
						<li>消息体。JMS定义的消息类型有TextMessage、MapMessage、BytesMessage、StreamMessage和ObjectMessage。</li>
				</ul>
				<p>1．2 JMS的可靠性机制<br />1．2．1 确认<br />    JMS消息只有在被确认之后，才认为已经被成功地消费了。消息的成功消费通常包含三个阶段：客户接收消息、客户处理消息和消息被确认。<br />    在事务性会话中，当一个事务被提交的时候，确认自动发生。在非事务性会话中，消息何时被确认取决于创建会话时的应答模式（acknowledgement mode）。该参数有以下三个可选值：</p>
				<ul>
						<li>Session.AUTO_ACKNOWLEDGE。当客户成功的从receive方法返回的时候，或者从MessageListener.onMessage方法成功返回的时候，会话自动确认客户收到的消息。</li>
						<li>Session.CLIENT_ACKNOWLEDGE。
客户通过消息的acknowledge方法确认消息。需要注意的是，在这种模式中，确认是在会话层上进行：确认一个被消费的消息将自动确认所有已被会话消
费的消息。例如，如果一个消息消费者消费了10个消息，然后确认第5个消息，那么所有10个消息都被确认。</li>
						<li>Session.DUPS_ACKNOWLEDGE。
该选择只是会话迟钝第确认消息的提交。如果JMS provider失败，那么可能会导致一些重复的消息。如果是重复的消息，那么JMS 
provider必须把消息头的JMSRedelivered字段设置为true。</li>
				</ul>
				<p>1．2．2 持久性<br />    JMS 支持以下两种消息提交模式：</p>
				<ul>
						<li>PERSISTENT。指示JMS provider持久保存消息，以保证消息不会因为JMS provider的失败而丢失。</li>
						<li>NON_PERSISTENT。不要求JMS provider持久保存消息。</li>
				</ul>
				<p>1．2．3 优先级<br />    可以使用消息优先级来指示JMS provider首先提交紧急的消息。优先级分10个级别，从0（最低）到9（最高）。如果不指定优先级，默认级别是4。需要注意的是，JMS provider并不一定保证按照优先级的顺序提交消息。</p>
				<p>
						<br />1．2．4 消息过期<br />    可以设置消息在一定时间后过期，默认是永不过期。</p>
				<p>
						<br />1．2．5 临时目的地<br />    可以通过会话上的createTemporaryQueue方法和createTemporaryTopic方法来创建临时目的地。它们的存在时间只限于创建它们的连接所保持的时间。只有创建该临时目的地的连接上的消息消费者才能够从临时目的地中提取消息。</p>
				<p>
						<br />1．2．6 持久订阅<br />    首先消息生产者必须使用PERSISTENT提交消息。客户可以通过会话上的createDurableSubscriber方法来创建一个持久订阅，该方法的第一个参数必须是一个topic。第二个参数是订阅的名称。<br />   
 JMS 
provider会存储发布到持久订阅对应的topic上的消息。如果最初创建持久订阅的客户或者任何其它客户使用相同的连接工厂和连接的客户ID、相同
的主题和相同的订阅名再次调用会话上的createDurableSubscriber方法，那么该持久订阅就会被激活。JMS 
provider会象客户发送客户处于非激活状态时所发布的消息。<br />    持久订阅在某个时刻只能有一个激活的订阅者。持久订阅在创建之后会一直保留，直到应用程序调用会话上的unsubscribe方法。</p>
				<p>
						<br />1．2．7 本地事务<br />   
 在一个JMS客户端，可以使用本地事务来组合消息的发送和接收。JMS 
Session接口提供了commit和rollback方法。事务提交意味着生产的所有消息被发送，消费的所有消息被确认；事务回滚意味着生产的所有消
息被销毁，消费的所有消息被恢复并重新提交，除非它们已经过期。<br />    事务性的会话总是牵涉到事务处理中，commit或rollback方法一旦被调用，一个事务就结束了，而另一个事务被开始。关闭事务性会话将回滚其中的事务。<br />需要注意的是，如果使用请求/回复机制，即发送一个消息，同时希望在同一个事务中等待接收该消息的回复，那么程序将被挂起，因为知道事务提交，发送操作才会真正执行。<br />    需要注意的还有一个，消息的生产和消费不能包含在同一个事务中。</p>
				<p>
						<br />1．3 JMS 规范的变迁<br />    JMS的最新版本的是1.1。它和同1.0.2版本之间最大的差别是，JMS1.1通过统一的消息传递域简化了消息传递。这不仅简化了JMS API，也有利于开发人员灵活选择消息传递域，同时也有助于程序的重用和维护。<br />以下是不同消息传递域的相应接口：</p>
				<table border="2">
						<tbody>
								<tr>
										<td>
												<strong>JMS 公共</strong>
										</td>
										<td>
												<strong>点对点域</strong>
										</td>
										<td>
												<strong>发布/订阅域</strong>
										</td>
								</tr>
								<tr>
										<td>ConnectionFactory</td>
										<td>QueueConnectionFactory</td>
										<td>TopicConnectionFactory</td>
								</tr>
								<tr>
										<td>Connection</td>
										<td>QueueConnection</td>
										<td>TopicConnection</td>
								</tr>
								<tr>
										<td>Destination</td>
										<td>Queue</td>
										<td>Topic</td>
								</tr>
								<tr>
										<td>Session</td>
										<td>QueueSession</td>
										<td>TopicSession</td>
								</tr>
								<tr>
										<td>MessageProducer</td>
										<td>QueueSender</td>
										<td>TopicPublisher</td>
								</tr>
								<tr>
										<td>MessageConsumer</td>
										<td>QueueReceiver</td>
										<td>TopicSubscriber</td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>2 ActiveMQ<br />2．1 Broker<br />2．1．1 Running Broker<br />    ActiveMQ5.0 的二进制发布包中bin目录中包含一个名为activemq的脚本，直接运行这个脚本就可以启动一个broker。<br />    此外也可以通过Broker Configuration URI或Broker XBean URI对broker进行配置，以下是一些命令行参数的例子：</p>
				<table border="2">
						<tbody>
								<tr>
										<td>
												<strong>Example</strong>
												<br />
										</td>
										<td>
												<strong>Description</strong>
												<br />
										</td>
								</tr>
								<tr>
										<td>activemq<br /></td>
										<td>Runs a broker using the default 'xbean:activemq.xml' as the broker configuration file.<br /></td>
								</tr>
								<tr>
										<td>activemq xbean:myconfig.xml<br /></td>
										<td>Runs a broker using the file myconfig.xml as the broker configuration file that is located in the classpath.<br /></td>
								</tr>
								<tr>
										<td>activemq xbean:file:./conf/broker1.xml<br /></td>
										<td>Runs
 a broker using the file broker1.xml as the broker configuration file 
that is located in the relative file path ./conf/broker1.xml<br /></td>
								</tr>
								<tr>
										<td>activemq xbean:file:C:/ActiveMQ/conf/broker2.xml<br /></td>
										<td>Runs
 a broker using the file broker2.xml as the broker configuration file 
that is located in the absolute file path C:/ActiveMQ/conf/broker2.xml<br /></td>
								</tr>
								<tr>
										<td>activemq broker:(tcp://localhost:61616, tcp://localhost:5000)?useJmx=true<br /></td>
										<td>Runs a broker with two transport connectors and JMX enabled.<br /></td>
								</tr>
								<tr>
										<td>activemq broker:(tcp://localhost:61616, network:tcp://localhost:5000)?persistent=false<br /></td>
										<td>Runs a broker with 1 transport connector and 1 network connector with persistence disabled.<br /></td>
								</tr>
						</tbody>
				</table>
				<p> </p>
				<p>2．1．2 Embedded Broker<br />    可以通过在应用程序中以编码的方式启动broker，例如：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span>BrokerService broker = </span>
												<span class="keyword">new</span>
												<span> BrokerService();  </span>
										</span>
								</li>
								<li>
										<span>broker.addConnector(<span class="string">"tcp://localhost:61616"</span><span>);  </span></span>
								</li>
								<li>
										<span>broker.start();  </span>
								</li>
						</ol>
				</div>    如果需要启动多个broker，那么需要为broker设置一个名字。例如：<div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>BrokerService broker = </span><span class="keyword">new</span><span> BrokerService();  </span></span></li><li><span>broker.setName(<span class="string">"fred"</span><span>);  </span></span></li><li><span>broker.addConnector(<span class="string">"tcp://localhost:61616"</span><span>);  </span></span></li><li><span>broker.start();  </span></li></ol></div>    如果希望在同一个JVM内访问这个broker，那么可以使用VM Transport，URI是：vm://brokerName。关于更多的broker属性，可以参考Apache的官方文档。<br />    此外，也可以通过BrokerFactory来创建broker，例如：<br /><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>BrokerService broker = BrokerFactory.createBroker(</span><span class="keyword">new</span><span> URI(someURI));  </span></span></li></ol></div>    someURI的可选值如下：<br /><table border="2"><tbody><tr><td><strong>URI scheme</strong></td><td><strong>Example</strong></td><td><strong>Description</strong></td></tr><tr><td>xbean:</td><td>xbean:activemq.xml</td><td>Searches
 the classpath for an XML document with the given URI (activemq.xml in 
this case) which will then be used as the Xml Configuration</td></tr><tr><td>file:</td><td>file:foo/bar/activemq.xml</td><td>Loads the given file (in this example foo/bar/activemq.xml) as the Xml Configuration</td></tr><tr><td>broker:</td><td>broker:tcp://localhost:61616</td><td>Uses the Broker Configuration URI to configure the broker</td></tr></tbody></table><br /><p>   当使用XBean的配置方式的时候，需要指定一个xml配置文件，例如：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>BrokerService broker = BrokerFactory.createBroker(</span><span class="keyword">new</span><span> URI(</span><span class="string">"xbean:com/test/activemq.xml"</span><span>));  </span></span></li></ol></div>    使用Spring的配置方式如下：<div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"broker"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.apache.activemq.xbean.BrokerFactoryBean"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"config"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"classpath:org/apache/activemq/xbean/activemq.xml"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">property</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"start"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．1．3 Monitoring Broker<br />2．1．3．1 JMX<br />    在使用JMX监控broker之前，首先要启用broker的JMX监控功能，例如在配置文件中设置useJmx="true"，如下：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="attribute">brokerName</span><span>="broker1</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">managementContext</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">managementContext</span><span> </span><span class="attribute">createConnector</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">managementContext</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  ...  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>   
 
接下来运行JDK自带的jconsole。在运行了jconsole后，它会弹出对话框来选择需要连接到的agent。如果是在启动broker的主机上
运行jconsole，那么ActiveMQ broker会出现在jconsole的Local 
标签中。如果要连接到远程的broker，那么可以在Advanced标签中指定JMX URL，以下是一个连接到本机的JMX URL：<br />    service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi<p>  
 
在jconsole的MBeans标签中，可以查看详细信息，也可以执行相应的operation。需要注意的是，在jconsole连接到broker
的时候，并不需要输入用户名和密码，如果这存在潜在的安全问题，那么就需要为JMX 
Connector配置密码保护（需要使用1.5以上版本的JDK）。    </p><p>   首先要禁止ActiveMQ创建自己的connector，例如：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>="localhost"</span><span class="attribute-value">useJmx</span><span>="true"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">managementContext</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">managementContext</span><span> </span><span class="attribute">createConnector</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">managementContext</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>    然后在ActiveMQ的conf目录下创建一个访问控制文件和密码文件，如下：<br />conf/jmx.access：<br /># The "monitorRole" role has readonly access.<br /># The "controlRole" role has readwrite access.<br />monitorRole readonly<br />controlRole readwrite<p> </p><p>conf/jmx.password：<br /># The "monitorRole" role has password "abc123".<br /># The "controlRole" role has password "abcd1234".<br />monitorRole abc123<br />controlRole abcd1234</p><p> </p><p>   然后修改ActiveMQ的bin目录下activemq的启动脚本，查找包含"SUNJMX="的一行如下：</p><p>REM
 set SUNJMX=-Dcom.sun.management.jmxremote.port=1616 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false<br />    把它替换成<br />set 
SUNJMX=-Dcom.sun.management.jmxremote.port=1616 
-Dcom.sun.management.jmxremote.authenticate=true 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.password.file=%ACTIVEMQ_BASE%/conf/jmx.password
 
-Dcom.sun.management.jmxremote.access.file=%ACTIVEMQ_BASE%/conf/jmx.access<br />   
 
最后重启ActiveMQ和jconsole，这时候需要强制login。如果在启动activemq的过程中出现以下错误，那么需要为这个文件增加访问
控制。Windows平台上的具体解决方法请参考如下网址：http://java.sun.com/j2se/1.5.0/docs/guide
/management/security-windows.html<br />Error: Password file read access must be restricted: D:\apache-activemq-5.0.0\bin\../conf/jmx.password</p><p> </p><p>2．1．3．2 Web Console<br />    Web Console被集成到了ActiveMQ的二进制发布包中，因此缺省访问http://localhost:8161/admin即可访问Web Console。<br />    在配置文件中，可以通过修改nioConnector的port属性来修改Web console的缺省端口：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">jetty</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://mortbay.com/schemas/jetty/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">connectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    <span class="tag">&lt;</span><span class="tag-name">nioConnector</span><span> </span><span class="attribute">port</span><span>=</span><span class="attribute-value">"8161"</span><span> </span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">connectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  ...  </span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">jetty</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>   
 出于安全性或者可靠性的考虑，Web Console 
可以被部署到不同于ActiveMQ的进程中。例如把activemq-web-console.war部署到一个单独的web容器中
（Tomcat，Jetty等）。在ActiveMQ5.0的二进制发布包中不包含activemq-web-console.war，因此需要下载
ActiveMQ的源码，然后进入到${activemq.base}/src/activemq-web-console目录中执行mvn 
instanll。如果一切正常，那么缺省会在${activemq.base}/src/activemq-web-console/target目录
中生成activemq-web-console-5.0.0.war。然后将activemq-web-console-5.0.0.war拷贝到
Tomcat的webapps目录中，并重命名成activemq-web-console.war。</p><p>   需要注意的是，要将activemq-all-5.0.0.jar拷贝到WEB-INF\lib目录中（可能还需要拷贝jms.jar）。还要为Tomcat设置以下五个系统属性（修改catalina.bat文件）：</p><p>set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.type="properties"<br />set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jms.url="tcp://localhost:61616"<br />set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.url="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"<br />set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.role="" <br />set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.password=""</p><p>  
 
如果JMX没有配置密码保护，那么webconsole.jmx.role和webconsole.jmx.password设置成""即可。如果
broker被配置成了Master/Slave模式，那么可以配置成使用failover transport，例如： </p><p>-Dwebconsole.jms.url=failover:(tcp://serverA:61616,tcp://serverB:61616)</p><p>  
 顺便说一下，由于webconsole.type 属性是properties，因此实际上起作用的Web 
Console的配置文件是WEB-INF/ 
webconsole-properties.xml。最后启动被监控的ActiveMQ，访问http://localhost:8080
/activemq-web-console/，查看显示是否正常。 </p><p> </p><p>2．1．3．3 Advisory Message<br />    ActiveMQ 支持Advisory Messages，它允许你通过标准的JMS 消息来监控系统。目前的Advisory Messages支持： </p><ul><li>consumers, producers and connections starting and stopping</li><li>temporary destinations being created and destroyed</li><li>messages expiring on topics and queues</li><li>brokers sending messages to destinations with no consumers.</li><li>connections starting and stopping</li></ul><p> 
 Advisory Messages可以被想象成某种的管理通道，通过它你可以得到关于JMS 
provider、producers、consumers和destinations的信息。Advisory 
topics都使用ActiveMQ.Advisory.这个前缀，以下是目前支持的topics：   </p><p>   Client based advisories</p><table border="2"><tbody><tr><td><strong>Advisory Topics</strong></td><td><strong>Description</strong></td></tr><tr><td>ActiveMQ.Advisory.Connection</td><td>Connection start &amp; stop messages</td></tr><tr><td>ActiveMQ.Advisory.Producer.Queue</td><td>Producer start &amp; stop messages on a Queue</td></tr><tr><td>ActiveMQ.Advisory.Producer.Topic</td><td>Producer start &amp; stop messages on a Topic</td></tr><tr><td>ActiveMQ.Advisory.Consumer.Queue</td><td>Consumer start &amp; stop messages on a Queue<br /></td></tr><tr><td>ActiveMQ.Advisory.Consumer.Topic</td><td>Consumer start &amp; stop messages on a Topic</td></tr></tbody></table><p class="MsoNormal" style="text-indent: 21pt; line-height: 150%;"> 

<br /><span style="">    在消费者启动</span><span style="line-height: 150%;">/</span><span style="">停止的</span><span style="line-height: 150%;">Advisory Messages</span><span style="">的消息头中有个</span><span style="line-height: 150%;">consumerCount</span><span style="">属性，他用来指明目前</span><span style="line-height: 150%;">desination</span><span style="">上活跃的</span><span style="line-height: 150%;">consumer</span><span style="">的数量。</span></p>     Destination and Message based advisories<br /><table border="2"><tbody><tr><td><strong>Advisory Topics</strong></td><td><strong>Description</strong></td></tr><tr><td>ActiveMQ.Advisory.Queue</td><td>Queue create &amp; destroy</td></tr><tr><td>ActiveMQ.Advisory.Topic</td><td>Topic create &amp; destroy</td></tr><tr><td>ActiveMQ.Advisory.TempQueue</td><td>Temporary Queue create &amp; destroy</td></tr><tr><td>ActiveMQ.Advisory.TempTopic</td><td>Temporary Topic create &amp; destroy</td></tr><tr><td>ActiveMQ.Advisory.Expired.Queue</td><td>Expired messages on a Queue</td></tr><tr><td>ActiveMQ.Advisory.Expired.Topic</td><td>Expired messages on a Topic</td></tr><tr><td>ActiveMQ.Advisory.NoConsumer.Queue</td><td>No consumer is available to process messages being sent on a Queue</td></tr><tr><td>ActiveMQ.Advisory.NoConsumer.Topic</td><td>No consumer is available to process messages being sent on a Topic</td></tr></tbody></table><p>  
 
以上的这些destnations都可以用来作为前缀，在其后面追加其它的重要信息，例如topic、queue、clientID、
producderID和consumerID等。这令你可以利用Wildcards 和 Selectors 来过滤Advisory 
Messages（关于Wildcard和Selector会在稍后介绍）。</p><p>   
例如，如果你希望订阅FOO.BAR这个queue上Consumer的start/stop的消息，那么可以订阅
ActiveMQ.Advisory.Consumer.Queue.FOO.BAR；如果希望订阅所有queue上的start/stop消息，那么可
以订阅ActiveMQ.Advisory.Consumer.Queue.&gt;；如果希望订阅所有queue或者topic上的
start/stop消息，那么可以订阅ActiveMQ.Advisory.Consumer. &gt;。</p><p>    org.apache.activemq.advisory.AdvisorySupport类上有如下的helper methods，用来在程序中得到advisory destination objects。</p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>AdvisorySupport.getConsumerAdvisoryTopic()  </span></span></li><li><span>AdvisorySupport.getProducerAdvisoryTopic()  </span></li><li><span>AdvisorySupport.getDestinationAdvisoryTopic()  </span></li><li><span>AdvisorySupport.getExpiredTopicMessageAdvisoryTopic()  </span></li><li><span>AdvisorySupport.getExpiredQueueMessageAdvisoryTopic()  </span></li><li><span>AdvisorySupport.getNoTopicConsumersAdvisoryTopic()  </span></li><li><span>AdvisorySupport.getNoQueueConsumersAdvisoryTopic()  </span></li></ol></div><p>   以下是段使用Advisory Messages的程序代码： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Java代码 </div></div><ol class="dp-j" start="1"><li><span><span>Destination advisoryDestination = AdvisorySupport.getProducerAdvisoryTopic(destination)  </span></span></li><li><span>MessageConsumer consumer = session.createConsumer(advisoryDestination);  </span></li><li><span>consumer.setMessageListener(<span class="keyword">this</span><span>);  </span></span></li><li><span>...  </span></li><li><span><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onMessage(Message msg){  </span></span></li><li><span>    <span class="keyword">if</span><span> (msg </span><span class="keyword">instanceof</span><span> ActiveMQMessage){  </span></span></li><li><span>        <span class="keyword">try</span><span> {  </span></span></li><li><span>             ActiveMQMessage aMsg =  (ActiveMQMessage)msg;  </span></li><li><span>             ProducerInfo prod = (ProducerInfo) aMsg.getDataStructure();  </span></li><li><span>        } <span class="keyword">catch</span><span> (JMSException e) {  </span></span></li><li><span>            log.error(<span class="string">"Failed to process message: "</span><span> + msg);  </span></span></li><li><span>        }  </span></li><li><span>    }  </span></li><li><span>}  </span></li></ol></div><p> </p><p>2．1．3．4 Command Agent<br />    在介绍Command Agent前首先简要介绍一下XMPP(Jabber)协议，XMPP是一种基于XML的即时通信协议，它由Jabber软件基金会开发。在配置文件中通过增加transportConnector来支持XMPP协议： </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>     ...  </span></li><li><span>     <span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"xmpp"</span><span>     </span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"xmpp://localhost:61222"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>    ActiveMQ提供了ActiveMQ messages和XMPP之间的双向桥接：<ul><li>如果客户加入了一个聊天室，那么这个聊天室的名字会被映射到一个JMS topic。</li><li>尝试在聊天室内发送消息会导致一个JMS消息被发送到这个topic。</li><li>呆在一个聊天室中意味着这将保持一个对相应JMS topic的订阅。因此发送到这个topic的JMS消息也会被发送到聊天室。</li></ul><p>   推荐XMPP客户端Spark(http://www.igniterealtime.org/)。 </p><p>   从4.2版本起，ActiveMQ支持Command Agent。在配置文件中，通过设置commandAgent来启用Command Agent：</p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>    ...  </span></li><li><span>  <span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>  <span class="tag">&lt;</span><span class="tag-name">commandAgent</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div>   
 启用了Command Agent的broker上会有一个来自Command Agent的连接，它同时订阅topic： 
ActiveMQ.Agent。在你启动XMPP客户端，加入到ActiveMQ.Agent聊天室后，就可以同broker进行交谈了。通过在XMPP
客户端中键入help，可以得到帮助信息。<br />    需要注意的是，ActiveMQ5.0版本有个小bug，如果broker没有采用缺省的用户名和密码，那么Command Agent便无法正常启动。Apache官方文档说，此bug已经被修正，预定在5.2.0版本上体现。修改方式如下：<div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">commandAgent</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerUser</span><span>=</span><span class="attribute-value">"user"</span><span> </span><span class="attribute">brokerPassword</span><span>=</span><span class="attribute-value">"passward"</span><span class="tag">/&gt;</span><span>  </span></span></li></ol></div><p> </p><p>2．1．3．5 Visualization plugin<br />    ActiveMQ支持以broker插件的形式生成DOT文件(可以用agrviewer来查看)，以图表的方式描述connections、sessions、producers、consumers、destinations等信息。配置方式如下：  </p><div class="dp-highlighter"><div class="bar"><div class="tools">Xml代码 </div></div><ol class="dp-xml" start="1"><li><span><span class="tag">&lt;</span><span class="tag-name">broker</span><span> </span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span> </span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"localhost"</span><span> </span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>      ...  </span></li><li><span>      <span class="tag">&lt;</span><span class="tag-name">plugins</span><span class="tag">&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">connectionDotFilePlugin</span><span>  </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"connection.dot"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>          <span class="tag">&lt;</span><span class="tag-name">destinationDotFilePlugin</span><span> </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"destination.dot"</span><span class="tag">/&gt;</span><span>  </span></span></li><li><span>      <span class="tag">&lt;/</span><span class="tag-name">plugins</span><span class="tag">&gt;</span><span>  </span></span></li><li><span><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>  </span></span></li></ol></div><p>  
 需要注意的是，笔者认为ActiveMQ5.0版本的Visualization 
Plugin尚不稳定，存在诸多问题。例如：如果使用connectionDotFilePlugin，那么brokerName必须是
localhost；如果使用destinationDotFilePlugin可能会导致ArrayStoreException。 </p></div>
<img src ="http://www.blogjava.net/libin2722/aggbug/330623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:25 <a href="http://www.blogjava.net/libin2722/articles/330623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>