activemq-artemis/docs/user-manual/zh/management.xml

806 lines
53 KiB
XML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================================= -->
<!-- Copyright © 2009 Red Hat, Inc. and others. -->
<!-- -->
<!-- The text of and illustrations in this document are licensed by Red Hat under -->
<!-- a Creative Commons AttributionShare Alike 3.0 Unported license ("CC-BY-SA"). -->
<!-- -->
<!-- An explanation of CC-BY-SA is available at -->
<!-- -->
<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
<!-- -->
<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
<!-- of it, you must provide the URL for the original version. -->
<!-- -->
<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
<!-- permitted by applicable law. -->
<!-- ============================================================================= -->
<chapter id="management">
<title>管理</title>
<para>ActiveMQ拥有套丰富的管理接口。用户使用这些接口可以修改服务器配置、创建新的资源如队列和
话题)、检查这些资源(如队列中有多少消息)并进行管理(从队列中删除消息)。这样用户可以
<emphasis>管理</emphasis>ActiveMQ。另外客户还可以订阅管理通知。</para>
<para>有三种方式管理ActiveMQ</para>
<itemizedlist>
<listitem>
<para>使用JMX -- JMX是标准的Java应用程序管理方式。</para>
</listitem>
<listitem>
<para>使用核心接口 -- 管理操作通过<emphasis>核心消息</emphasis>的方法发向ActiveMQ服
务。</para>
</listitem>
<listitem>
<para>使用JMS接口 -- 管理操作通过<emphasis>JMS消息</emphasis>的方式发向ActiveMQ服务器。</para>
</listitem>
</itemizedlist>
<para>虽然有三种方式但它们提供相同的功能。使用JMX方法能完成的功能使用核心接口或JMS接口都可以完成。</para>
<para>根据不同的应用环境来选择最适当的方式。</para>
<section>
<title>管理接口API</title>
<para>不管使用哪种方式,管理接口都是一样的。</para>
<para>对于每个<emphasis>被管理的资源</emphasis>都有一个Java的接口提供可使用的操作。</para>
<para>ActiveMQ的管理接口分布在2个包中</para>
<itemizedlist>
<listitem>
<para><emphasis>核心</emphasis>资源的管理接口在 <literal
>org.apache.activemq.api.core.management</literal>包中。</para>
</listitem>
<listitem>
<para><emphasis>JMS</emphasis>资源的管理接口在 <literal
>org.apache.activemq.api.jms.management</literal>包中。</para>
</listitem>
</itemizedlist>
<para>调用<emphasis>管理操作</emphasis>的方法由所使用是方式是JMX、核心消息还是JMS
消息来决定。</para>
<note>
<para>一小部分的管理接口需要一个<literal>过滤器</literal>参数来选择需要的消息。
如果要求<emphasis>所有的消息</emphasis>,传递该参数时使用<literal>
null</literal>或者一个空的字符串即可。</para>
</note>
<section>
<title>核心管理接口</title>
<para>ActiveMQ定义了一套对核心资源的管理接口。关于它们的详细说明请参见相应的javadoc。
下面是对它们的概述:</para>
<section>
<title>核心服务器管理</title>
<itemizedlist>
<listitem>
<para>队列的列表、创建、部署与删除</para>
<para><literal>getQueueNames()</literal> method方法用来列出所有已经部署的队列。</para>
<para><literal>ActiveMQServerControl</literal> ObjectName <literal
>org.apache.activemq:module=Core,type=Server</literal>或资源名<literal
>core.server</literal>)上有队列创建或删除的方法,它们是
<literal>createQueue()</literal><literal>deployQueue()</literal>
<literal>destroyQueue()</literal></para>
<para>如果队列已经存在,那么<literal>createQueue</literal>方法调用会出错,而
<literal>deployQueue</literal>方法调用没有任何作用。</para>
</listitem>
<listitem>
<para>暂停与恢复队列</para>
<para><literal>QueueControl</literal>可用来暂停与恢复队列。如果一个队列被暂停,它
虽然可以继续接收消息但是不传递消息;当被恢复时,队列又会开始传递消息。
</para>
</listitem>
<listitem>
<para>远程连接的列表与关闭</para>
<para><literal>listRemoteAddresses()</literal>方法可以用来列出客户端的远程地址。
还可以使用<literal>closeConnectionsForAddress()</literal>方法来关闭
与该地址相关的远程连接。</para>
<para>另外,使用<literal>listConnectionIDs()</literal>方法可以列出连接ID
使用<literal>listSessions()</literal>方法可以列出与一个连接ID相关的所有
会话session</para>
</listitem>
<listitem>
<para>事务的手动操作heuristic operations</para>
<para>当服务器由于故障而重新启动时,可能造成一些事务没有完成而需要人工干预。
<literal>listPreparedTransactions()</literal>方法可以列出所有处于
准备prepared状态的事务事务是用Base64字符串的形式列出。如果要提交或回滚
可以使用<literal>commitPreparedTransaction()</literal>方法或
<literal>rollbackPreparedTransaction()</literal>方法。采用启发式
heuristic完成的事务可以用<literal>listHeuristicCommittedTransactions()</literal>
方法和<literal>listHeuristicRolledBackTransactions</literal>方法列出。</para>
</listitem>
<listitem>
<para>打开和重置消息计数器</para>
<para>消息计数器可以用<literal>enableMessageCounters()</literal>方法打开,用
<literal>disableMessageCounters()</literal>方法关闭。如果要重置消息计数器,
可以使用<literal>resetAllMessageCounters()</literal>方法和
<literal>resetAllMessageCounterHistories()</literal>方法。</para>
</listitem>
<listitem>
<para>获得服务器的配置和属性</para>
<para><literal>ActiveMQServerControl</literal>提供了访问ActiveMQ服务器所有属性
的方法(例如<literal>getVersion()</literal>方法可以得到服务器的版本,等等)。 </para>
</listitem>
<listitem>
<para>核心桥和转发器的创建,删除与列表</para>
<para>使用<literal>getBridgeNames()</literal>可以列出部署的核心桥。
使用<literal>getDivertNames()</literal>可以列出部署的转发器。</para>
<para>使用<literal>ActiveMQServerControl</literal> (ObjectName <literal
>org.apache.activemq:module=Core,type=Server</literal> 或资源名 <literal
>core.server</literal>)的方法<literal>createBridge()</literal>
             <literal>destroyBridge()</literal>可以创建和删除核心桥。
通过<literal>createDivert()</literal><literal>destroyDivert()</literal>
可以创建和删除转发器。</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>核心地址的管理</title>
<para>核心地址可以通过<literal>AddressControl</literal>类进行访问ObjectName
<literal>org.apache.activemq:module=Core,type=Address,name="&lt;the
address name&gt;"</literal>或者资源名 <literal>core.address.&lt;the
address name&gt;</literal>)。</para>
<itemizedlist>
<listitem>
<para>修改地址的角色和权限。</para>
<para>你可以使用<literal>addRole()</literal>方法或<literal>removeRole()</literal>
方法添加或删除地址的角色。用<literal>getRoles()</literal>方法可以列出一个地址的所有角色。</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>核心队列的管理</title>
<para>管理接口中的一大部分是管理核心队列的。<literal>QueueControl</literal>类定义了核心队列的管理
接口ObjectName <literal>org.apache.activemq:module=Core,type=Queue,address="&lt;绑定地址
address&gt;",name="&lt;队列名&gt;"</literal> 或资源名 <literal
>core.queue.&lt;队列名&gt;</literal>)。</para>
<para>绝大部分的队列管理方法需要一个消息ID参数如删除一个消息或一个过滤器参数如将具有某个
属性值的所有消息设置为过期)。</para>
<itemizedlist>
<listitem>
<para>消息的过期,发向死信地址及删除</para>
<para><literal>expireMessages()</literal>方法可以使消息过期。如果设置了一个过期地址,
这些消息会被发到过期地址。否则这些消息会被丢弃。<literal>setExpiryAddress()</literal>
方法可以用来设置队列的过期地址。</para>
<para>消息可以用<literal>sendMessagesToDeadLetterAddress()</literal>方法发送到
一个死信地址。它返回发到这个死信地址的消息的数量。如果没有设置死信地址,那么消息就会从队列中
删除。用<literal>setDeadLetterAddress()</literal>方法可以设置队列的死信地址。</para>
<para>消息还可以从一个队列转移到另一个队列。其方法是
<literal>moveMessages()</literal></para>
</listitem>
<listitem>
<para>消息的列表与删除</para>
<para><literal>listMessages()</literal>方法可以列出一个队列中的所有消息。这个方法
返回的是一个<literal>Map</literal>的数组。每一个Map对应一个消息。</para>
<para>消息可以用<literal>removeMessages()</literal>方法删除。如果是使用消息ID
返回的是一个布尔常量;如果是用过滤器,则返回的
是删除的消息数量。在使用过滤器来删除过滤的消息时,如果传入一个空字符串则表示要删除
所有的消息。</para>
</listitem>
<listitem>
<para>消息计数</para>
<para>一个队列中的消息数可以用<literal>getMessageCount()</literal>方法获得。
此外,<literal>countMessages()</literal>方法可以返回队列中与一
<emphasis>过滤器</emphasis>匹配的消息数量。</para>
</listitem>
<listitem>
<para>修改消息的优先级</para>
<para><literal>changeMessagesPriority()</literal>方法可以改变消息的优先级。
该方法如果带一个消息ID参数返回一个布尔常量如果带一个过滤器参数返回优先级
被更新的消息的数量。</para>
</listitem>
<listitem>
<para>消息计数器</para>
<para><literal>listMessageCounter()</literal>方法和<literal>
listMessageCounterHistory()</literal>方法可以列出一个队列的消息计数器。
(参见 <xref linkend="management.message-counters"/>)。消息计数器还可以
<literal>resetMessageCounter()</literal>方法重置。</para>
</listitem>
<listitem>
<para>获得队列的属性</para>
<para>通过<literal>QueueControl</literal>可以获得核心队列的属性(例如用
<literal>getFilter()</literal>方法可以得到队列的
过滤器,<literal>isDurable()</literal>方法可以知道队列是否是持久的队列等等)。</para>
</listitem>
<listitem>
<para>暂停和恢复队列</para>
<para><literal>QueueControl</literal>可用来暂停与恢复队列。如果一个队列被暂停,它
虽然可以继续接收消息但是不传递消息;当被恢复时,队列又会开始传递消息。</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>其它核心资源的管理</title>
<para>ActiveMQ允许用户启动或停止其远程资源接收器转发器等等。这样可以使服务器暂停工作
而不需要完全停止服务器(比如可以临时对服务器进行一些离线操作,像对一些事务的处理)。这些资源有:</para>
<itemizedlist>
<listitem>
<para>接收器</para>
<para><literal>AcceptorControl</literal>ObjectName <literal
>org.apache.activemq:module=Core,type=Acceptor,name="&lt;接收器名
&gt;"</literal> 或资源名 <literal>core.acceptor.&lt;地址名
&gt;</literal>)的<literal>start()</literal>方法启动,用<literal>
stop()</literal>方法停止。接收器的参数可以通过<literal>AcceptorControl</literal>
的属性获得。(参见 <xref
linkend="configuring-transports.acceptors"/>)。</para>
</listitem>
<listitem>
<para>转发器</para>
<para><literal>DivertControl</literal>ObjectName是 <literal
>org.apache.activemq:module=Core,type=Divert,name=&lt;转发器名&gt;</literal>
或资源名<literal>core.divert.&lt;转发器&gt;</literal>)类的
<literal>start()</literal>方法可以启动,用<literal>stop()</literal>方法可以停止。
通过<literal>DivertControl</literal>还可以获得转发器的各种属性。(参见 <xref
linkend="diverts"/>)。</para>
</listitem>
<listitem>
<para></para>
<para>桥可以通过<literal>BridgeControl</literal>ObjectName <literal
>org.apache.activemq:module=Core,type=Bridge,name="&lt;桥的名字
&gt;"</literal> 或资源名 <literal>core.bridge.&lt;桥的名字
&gt;</literal>)的<literal>start()</literal>
方法启动,用<literal>stop()</literal>方法停止。它的属性可以通过
<literal>BridgeControl</literal>的属性获得(参见
<xref linkend="core-bridges"/>)。</para>
</listitem>
<listitem>
<para>广播组</para>
<para>广播组可以通过<literal>BroadcastGroupControl</literal>ObjectName <literal
>org.apache.activemq:module=Core,type=BroadcastGroup,name="&lt;广播组名
&gt;"</literal> 或者资源名 <literal
>core.broadcastgroup.&lt;广播组名&gt;</literal>)的<literal>
start()</literal>方法启动,用<literal>stop()</literal>方法停止。
它的属性也可以通过<literal
>BroadcastGroupControl</literal>的属性获得(参见<xref
linkend="clusters.broadcast-groups"/>)。</para>
</listitem>
<listitem>
<para>发现组</para>
<para>发现组可以通过<literal>DiscoveryGroupControl</literal>
ObjectName <literal>org.apache.activemq:module=Core,type=DiscoveryGroup,
name="&lt;发现组名&gt;"</literal> 或资源名<literal>core.discovery.&lt;
发现组名&gt;</literal>)的
<literal>start()</literal>方法启动,用<literal>stop()</literal>方法停止。
它的参数可以通过<literal>DiscoveryGroupControl</literal>的属性获得(参见
<xref linkend="clusters.discovery-groups"/>)。</para>
</listitem>
<listitem>
<para>集群连接</para>
<para>集群连接可以通过<literal>ClusterConnectionControl</literal>类(
ObjectName <literal
>org.apache.activemq:module=Core,type=ClusterConnection,name="&lt;集群连接名
&gt;"</literal> 或资源名 <literal
>core.clusterconnection.&lt;集群连接名&gt;</literal>)的<literal>
start()</literal>方法启动,用<literal>stop()</literal>方法停止。
它的参数可以通过<literal
>ClusterConnectionControl</literal>的属性来获得(参见
<xref linkend="clusters.cluster-connections"/>)。</para>
</listitem>
</itemizedlist>
</section>
</section>
<section>
<title>JMS管理接口</title>
<para>ActiveMQ定义了一套JMS管理接口来管理JMS的<emphasis>可管理的对象</emphasis>
例如JMS队列话题及连接工厂</para>
<section>
<title>JMS服务器管理</title>
<para><literal>JMSServerControl</literal>ObjectName <literal
>org.apache.activemq:module=JMS,type=Server</literal> 或资源名<literal
>jms.server</literal>用来创建JMS资源连接工厂和目标</para>
<itemizedlist>
<listitem>
<para>列表、创建、删除连接工厂</para>
<para>使用<literal>getConnectionFactoryNames()</literal> 方法可以列出部署的连接工厂的
名字。</para>
<para><literal>createConnectionFactory()</literal>方法和<literal
>destroyConnectionFactory()</literal>方法能创建和删除JMS连接工厂。
这些连接工厂都与JNDI绑定以便于客户端来查找。如果是在图形介面下创建连接工厂在广本框内输入
有关的传输参数时可使用一组用逗号隔开的键-值对(例如<literal>key1=10, key2="value", key3=false</literal>)。
如果需要定义多个传输,你需要将每个传输的参数对用大括号括起来,例如<literal>{key=10}, {key=20}</literal>
第一个<literal>key</literal>属于第一个传输配置,第二个<literal>key</literal>属于第二个传输配置。
(有关传输的各种参数参见<xref linkend="configuring-transports"/>)。</para>
</listitem>
<listitem>
<para>列表、创建与删除队列</para>
<para><literal>getQueueNames()</literal>方法可以获得部署的JMS队列的名字列表。</para>
<para>JMS队列可以用<literal>createQueue()</literal>方法创建,用<literal>destroyQueue()</literal>方法删除。
创建的队列都绑定到JNDI以便JMS客户端可以查找。</para>
</listitem>
<listitem>
<para>列表、创建与删除话题topic</para>
<para><literal>getTopicNames()</literal>方法可以获得部署的JMS话题名字。</para>
<para>JMS话题可以用<literal>createTopic()</literal>方法来创建,用<literal>destroyTopic()</literal>方法来删除。
创建的话题都绑定到JNDI以便客户端查找。</para>
</listitem>
<listitem>
<para>远程连接的列表与关闭</para>
<para><literal>listRemoteAddresses()</literal>方法可以获得JMS客户端的远程地址。
还可以用<literal>closeConnectionsForAddress()</literal>方法关闭与某个远程地址相关联的连接。</para>
<para>另外,<literal>listConnectionIDs()</literal>方法可以列出连接的ID
<literal>listSessions()</literal>方法可以列出一个给定的连接ID的所有会话session</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>JMS连接工厂的管理</title>
<para>使用类ObjectName <literal>org.apache.activemq:module=JMS,type=ConnectionFactory,
name="&lt;连接工厂名&gt;"</literal>或者资源名<literal>jms.connectionfactory.&lt;
连接工厂名&gt;</literal>可以管理JMS的连接工厂。</para>
<itemizedlist>
<listitem>
<para>获得连接工厂的属性</para>
<para><literal>ConnectionFactoryControl</literal>类可以用来获得连接工厂的属性(
例如<literal>getConsumerWindowSize()</literal>方法可以获得接收者流控制的窗口大小,
<literal>isBlockOnNonDurableSend()</literal>方法可以知道从这个连接工厂创建的发送
者是否采用阻塞方式发送非持久的消息,等等)。</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>JMS队列管理</title>
<para>使用<literal>JMSQueueControl</literal>ObjectName <literal>org.apache.activemq:module=JMS,
type=Queue,name="&lt;队列名&gt;"</literal>或资源名 <literal>jms.queue.&lt;队列名
&gt;</literal>可以管理JMS队列。</para>
<para><emphasis>JMS队列的管理操作与核心队列的管理十分相似。</emphasis></para>
<itemizedlist>
<listitem>
<para>过期,发送到死信地址和移动消息</para>
<para>可以使用<literal>expireMessages()</literal>方法将队列中的消息设成过期消息。
如果配置有过期地址,消息就会被发到过期地址。过期地址可以用
<literal>setExpiryAddress()</literal>方法来设定。</para>
<para>使用<literal>sendMessagesToDeadLetterAddress()</literal>方法可以将消息发送到死信地址。
它返回发送到死信地址消息的数量。如果没有设定死信地址,那么消息会被丢弃。使用
<literal>setDeadLetterAddress()</literal>方法可以设定队列的死信地址。</para>
<para><literal>moveMessages()</literal>方法将消息从一个队列移动到另一个队列。</para>
</listitem>
<listitem>
<para>列表与删除消息</para>
<para>使用<literal>listMessages()</literal>方法可以列出一个队列中的所有消息。它返回的是一个
Map的数组。每一个Map对应一个消息。</para>
<para>使用<literal>removeMessages()</literal>方法可以从队列中删除消息。如果带的参数是消息ID
返回的是一个布尔常是;如果带的参数是一个过滤器,则返回删除的消息数。带有过滤器参数的<literal
>removeMessages()</literal>方法只删除过滤器选择的消息。如果些参数是一个空字符串,那么将
删除所有的消息。</para>
</listitem>
<listitem>
<para>消息计数</para>
<para>使用<literal>getMessageCount()</literal>方法可以得到队列中的消息数。另外,方法
<literal>countMessages()</literal>可以得到队列中所有与<emphasis>过滤器</emphasis>相匹配的消息数。</para>
</listitem>
<listitem>
<para>修改消息的优先级</para>
<para>消息的优先级可以用<literal>changeMessagesPriority()</literal>方法修改。如果是带一个消
息ID参数它返回的是一个布尔常量如果是带一个过滤器参数则它返回的是优先级更新了的消息数。</para>
</listitem>
<listitem>
<para>消息计数器</para>
<para><literal>listMessageCounter()</literal>方法和<literal >listMessageCounterHistory()</literal>
方法可以用来列出队列中的所有消息计数器。(参见 <xref
linkend="management.message-counters"/>)。</para>
</listitem>
<listitem>
<para>获取队列的属性</para>
<para><literal>JMSQueueControl</literal>类可以用来获取JMS队列的设置参数例如方法<literal>isTemporary()</literal>
可以判断队列是否为临时的,方法<literal>isDurable()</literal>可以判断队列是否为持久的等等)。</para>
</listitem>
<listitem>
<para>队列的暂停与恢复</para>
<para><literal>JMSQueueControl</literal>可以暂停一个队列或恢复一个队列。
如果一个队列被暂停,它虽然可以继续接收消息但是不传递消息;
当被恢复时,队列又会开始传递消息。</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>JMS话题Topic的管理</title>
<para>JMS话题的管理是通过<literal>TopicControl</literal>类(
the ObjectName <literal>org.apache.activemq:module=JMS,type=Topic,name="&lt;话题名&gt;"</literal>
或资源名 <literal>jms.topic.&lt;话题名&gt;</literal>)。</para>
<itemizedlist>
<listitem>
<para>订阅和消息的列表</para>
<para><literal>listAllSubscriptions()</literal><literal
>listDurableSubscriptions()</literal><literal
>listNonDurableSubscriptions()</literal>方法可以列出话题的不同订阅。
这些方法都返回<literal>Object</literal>数组,表示订阅的细节(如订阅名,
客户ID持久性消息计数等。用<literal
>listMessagesForSubscription()</literal>方法可以列出一个订阅上的JMS消息。</para>
</listitem>
<listitem>
<para>删除订阅</para>
<para>持久性订阅可以使用<literal>dropDurableSubscription()</literal>方法来删除。</para>
</listitem>
<listitem>
<para>订阅消息计数</para>
<para><literal>countMessagesForSubscription()</literal>方法可以得到一个订阅上面所持有
的消息数(还可带一个消息选择器来得出有多少消息与之匹配)。</para>
</listitem>
</itemizedlist>
</section>
</section>
</section>
<section id="management.jmx">
<title>使用JMX</title>
<para>ActiveMQ提供了<ulink
url="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/"
>JMX</ulink></para>
<para>ActiveMQ通过MBean的接口暴露其JMX管理操作。它将自己的资源注册到<literal>org.apache.activemq</literal>域。</para>
<para>比如,用来管理一个名为<literal>exampleQueue</literal>JMS队列的<literal>ObjectName</literal>是:</para>
<programlisting>
org.apache.activemq:module=JMS,type=Queue,name="exampleQueue"
</programlisting>
<para>MBean为</para>
<programlisting>
org.apache.activemq.api.jms.management.JMSQueueControl
</programlisting>
<para>MBean的<literal>ObjectName</literal><literal
>org.apache.activemq.api.core.management.ObjectNameBuilder</literal>来产生出来的。你也可以使用<literal
>jconsole</literal>来查找你想要的MBean的<literal>ObjectName</literal></para>
<para>使用JMX来管理ActiveMQ与用JMX管理其它Java应用程序没有什么不同。你可以使用反射或者创建MBean代理的方法。</para>
<section id="management.jmx.configuration">
<title>配置JMX</title>
<para>默认情况下ActiveMQ的JMX是打开的。将<literal
>activemq-configuration.xml</literal>文件中的<literal
>jmx-management-enabled</literal>设置为<literal>false</literal>就可以关闭JMX</para>
<programlisting>
&lt;!-- false to disable JMX management for ActiveMQ --&gt;
&lt;jmx-management-enabled&gt;false&lt;/jmx-management-enabled&gt;
</programlisting>
<para>如果JMX功能是打开的则使用<literal>jconsole</literal>可以管理本地的ActiveMQ。</para>
<note>
<para>出于安全考虑默认情况下JMX远程连接是关闭的。参见<ulink url="http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#remote"
>Java管理指南</ulink>来配置服务器的远程管理(系统变量必须在<literal>run.sh</literal><literal>run.bat</literal>中定义)。</para>
</note>
<para>ActiveMQ默认使用JMX域名"org.apache.activemq"。如果要用一个MBeanServer管理多个ActiveMQ服务器可以将每个ActiveMQ
服务器配置成不同的JMX域。方法就是在<literal>activemq-configuration.xml</literal>文件中设置<literal>jmx-domain</literal></para>
<programlisting>
&lt;!-- use a specific JMX domain for ActiveMQ MBeans -->
&lt;jmx-domain>my.org.apache.activemq&lt;/jmx-domain>
</programlisting>
<section>
<title>MBeanServer的配置</title>
<para>ActiveMQ在独立运行时使用Java虚拟机的<literal
>Platform MBeanServer</literal>来注册其MBean。这在JBoss Microcontainer微容器的bean
文件中进行配置(参见<xref linkend="server.microcontainer.configuration"/></para>
<programlisting>&lt;!-- MBeanServer --&gt;
&lt;bean name="MBeanServer" class="javax.management.MBeanServer"&gt;
&lt;constructor factoryClass="java.lang.management.ManagementFactory"
factoryMethod="getPlatformMBeanServer" /&gt;
&lt;/bean&gt;
</programlisting>
<para>当与AS 5集成运行时它使用应用服务器自己的MBean服务这样就可以使用它的jmx-console</para>
<programlisting>&lt;!-- MBeanServer --&gt;
&lt;bean name="MBeanServer" class="javax.management.MBeanServer"&gt;
&lt;constructor factoryClass="org.jboss.mx.util.MBeanServerLocator"
factoryMethod="locateJBoss" /&gt;
&lt;/bean&gt;
</programlisting>
</section>
</section>
<section>
<title>例子</title>
<para>参见<xref linkend="examples.jmx"/>这个例子展示了如何使用远程JMX连接或MBean代理来管理ActiveMQ。</para>
</section>
</section>
<section>
<title>使用核心接口</title>
<para>核心管理接口的调用实际上是向一个特殊的地址发送核心消息。这个特殊地址称为<emphasis>管理地址</emphasis></para>
<para><emphasis>管理消息</emphasis>是一些定义了一些固定属性的普通核心消息。服务器通过这些属性来解释管理操作:</para>
<itemizedlist>
<listitem>
<para>管理资源的名称</para>
</listitem>
<listitem>
<para>管理操作的名称</para>
</listitem>
<listitem>
<para>管理操作的参数</para>
</listitem>
</itemizedlist>
<para>当一个管理消息发送到管理地址时ActiveMQ服务器将从中提取出相应的信息再调用相应的管理资源的方法之后向
该管理消息的回答地址reply-to address<literal>ClientMessageImpl.REPLYTO_HEADER_NAME
</literal>定义)发送一个<emphasis>管理回答</emphasis></para>
<para>一个<literal>ClientConsumer</literal>用来接收管理回答并提取出其中的操作的結果(如果有的话)。
考虑到可移植性返回的結果采用的是格式的字符串而没有采用Java的序列化技术
<literal>org.apache.activemq.api.core.management.ManagementHelper</literal>可以用来将JSON字符串
转换成Java对象</para>
<para>使用以下步骤可以简化使用核心消息调用管理操作:</para>
<orderedlist>
<listitem>
<para>创建一个<literal>ClientRequestor</literal>对象,用来发送管理消息并接收回答。</para>
</listitem>
<listitem>
<para>创建一个<literal>ClientMessage</literal></para>
</listitem>
<listitem>
<para>使用<literal
>org.apache.activemq.api.core.management.ManagementHelper</literal>类来帮助设置消息的管理参数。</para>
</listitem>
<listitem>
<para>通过<literal>ClientRequestor</literal>将消息发送</para>
</listitem>
<listitem>
<para>使用 <literal
>org.apache.activemq.api.core.management.ManagementHelper</literal>类从管理操作結果中提取返回值。</para>
</listitem>
</orderedlist>
<para>例如,要得到核心队列<literal>exampleQueue</literal>中消息的数量:</para>
<programlisting>
ClientSession session = ...
ClientRequestor requestor = new ClientRequestor(session, "jms.queue.hornetq.management");
ClientMessage message = session.createMessage(false);
ManagementHelper.putAttribute(message, "core.queue.exampleQueue", "messageCount");
ClientMessage reply = requestor.request(m);
int count = (Integer) ManagementHelper.getResult(reply);
System.out.println("There are " + count + " messages in exampleQueue");
</programlisting>
<para>管理操作名及其参数必须和<literal>management</literal>包中定义的Java接口一致。</para>
<para>资源的名称是用<literal>org.apache.activemq.api.core.management.ResourceNames</literal>类来生成的,
命名都非常直观(如核心队列<literal>exampleQueue</literal>的名称为<literal>core.queue.exampleQueue</literal>
JMS Topic <literal>exampleTopic</literal>的名称为<literal>jms.topic.exampleTopic</literal>,等等)。
</para>
<section id="management.core.configuration">
<title>配置核心管理</title>
<para>管理地址的配置在文件<literal
>activemq-configuration.xml</literal>中:</para>
<programlisting>
&lt;management-address&gt;jms.queue.hornetq.management&lt;/management-address&gt;
</programlisting>
<para>它的默认地址是<literal>jms.queue.hornetq.management</literal> (地址前缀加上
“jms.queue”是为了方便JMS客户端也可以向它发送管理消息。</para>
<para>管理地址需要一个<emphasis>特殊</emphasis>的用户权限
<literal>manage</literal>来接收并处理管理消息。这个权限也在hornetq-configuration.xml文件中配置</para>
<programlisting>
&lt;!-- users with the admin role will be allowed to manage --&gt;
&lt;!-- ActiveMQ using management messages --&gt;
&lt;security-setting match="jms.queue.hornetq.management"&gt;
&lt;permission type="manage" roles="admin" /&gt;
&lt;/security-setting&gt;
</programlisting>
</section>
</section>
<section id="management.jms">
<title>使用JMS进行管理</title>
<para>使用JMS管理ActiveMQ与使用核心API管理ActiveMQ十分相似。</para>
<para>其中一个重要的不同是JMS需要一个JMS队列来发送消息而核心接口使用的是一个地址</para>
<para><emphasis>管理队列</emphasis>是一个特殊的队列,它需要客户端直接实例化:</para>
<programlisting>
Queue managementQueue = ActiveMQJMSClient.createQueue("hornetq.management");
</programlisting>
<para>其余步骤完全和使用核心接口一样,只是相应的对象不同:</para>
<orderedlist>
<listitem>
<para>创建一个<literal>QueueRequestor</literal>来向管理地址发送管理消息并接收回答。</para>
</listitem>
<listitem>
<para>创建一个<literal>消息</literal></para>
</listitem>
<listitem>
<para>使用 <literal>org.apache.activemq.api.jms.management.JMSManagementHelper</literal>类向消息中设置管理参数。</para>
</listitem>
<listitem>
<para>再使用<literal>QueueRequestor</literal>发送消息。</para>
</listitem>
<listitem>
<para>使用<literal>org.apache.activemq.api.jms.management.JMSManagementHelper</literal>来从回答中提取返回結果。</para>
</listitem>
</orderedlist>
<para>例如要得到一个JMS队列<literal>exampleQueue</literal>中有多少消息:</para>
<programlisting>
Queue managementQueue = ActiveMQJMSClient.createQueue("hornetq.management");
QueueSession session = ...
QueueRequestor requestor = new QueueRequestor(session, managementQueue);
connection.start();
Message message = session.createMessage();
JMSManagementHelper.putAttribute(message, "jms.queue.exampleQueue", "messageCount");
Message reply = requestor.request(message);
int count = (Integer)JMSManagementHelper.getResult(reply);
System.out.println("There are " + count + " messages in exampleQueue");
</programlisting>
<section>
<title>配置JMS管理</title>
<para>JMS管理的配置与核心接口管理的配置步骤是一样的参见<xref linkend="management.core.configuration"/>)。</para>
</section>
<section>
<title>例子</title>
<para>参见<xref linkend="examples.management"/>它展示了如何使用JMS消息来管理ActiveMQ。</para>
</section>
</section>
<section id="management.notifications">
<title>管理通知</title>
<para>ActiveMQ可以向listener发送各种事件的<emphasis>通知</emphasis>(如资源的创建,安全破坏等)。</para>
<para>有三种方式接收管理通知</para>
<itemizedlist>
<listitem>
<para>JMX通知</para>
</listitem>
<listitem>
<para>核心消息</para>
</listitem>
<listitem>
<para>JMS消息</para>
</listitem>
</itemizedlist>
<section>
<title>JMX通知</title>
<para>如果设置了JMX参见<xref linkend="management.jmx.configuration"/>),就可以通过订阅以下
两个MBean来获得通知</para>
<itemizedlist>
<listitem>
<para><literal>org.apache.activemq:module=Core,type=Server</literal> 可以获得有关
<emphasis>核心</emphasis>资源的通知</para>
</listitem>
<listitem>
<para><literal>org.apache.activemq:module=JMS,type=Server</literal>可以获得有关
<emphasis>JMS</emphasis>资源的通知</para>
</listitem>
</itemizedlist>
</section>
<section>
<title>核心消息通知</title>
<para>ActiveMQ定义了一个特殊的<emphasis>管理通知地址</emphasis>。核心队列绑定到该地址后,客户
端就可以接收以核心消息形式发送的管理信通知了。</para>
<para>一个核心客户端要想接收到管理通知,它必须要创建一个队列并绑定到这个管理通知地址上,然后从这个
队列接收通知。</para>
<para>通知消息就是普通的核心消息加上相关的属性(如通知类型,事件发生时间,资源等)。</para>
<para>由于是标准的核心消息,使用选择器还能够过滤掉一部分通知而只接收感兴趣的通知。</para>
<section id="management.notifications.core.configuration">
<title>配置核心管理通知地址</title>
<para>用来发送管理通知的地址在文件中<literal>activemq-configuration.xml</literal>配置:</para>
<programlisting>
&lt;management-notification-address&gt;hornetq.notifications&lt;/management-notification-address&gt;
</programlisting>
<para>默认的地址是<literal>hornetq.notifications</literal></para>
</section>
</section>
<section>
<title>JMS消息通知</title>
<para>ActiveMQ还可以通过JMS消息的方式发送通知。</para>
<para>这种方式与核心消息通知相似但是有一个重要的不同JMS消息需要一个JMS的目标通常是一个Topic</para>
<para>要通过一个JMS目标来接收管理通知必须将服务器的管理通知地址修改为以<literal>jms.queue</literal>开头(如果是一个
JMS队列或者<literal>jms.topic</literal>(如果是一个话题):</para>
<programlisting>
&lt;!-- 通知将从JMS话题 "notificationsTopic"上接收 -->
&lt;management-notification-address&gt;jms.topic.notificationsTopic&lt;/management-notification-address&gt;
</programlisting>
<para>这个通知话题一旦被创建,就可以接收消息了(或者使用<literal>MessageListener</literal></para>
<programlisting>
Topic notificationsTopic = ActiveMQJMSClient.createTopic("notificationsTopic");
Session session = ...
MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic);
notificationConsumer.setMessageListener(new MessageListener()
{
public void onMessage(Message notif)
{
System.out.println("------------------------");
System.out.println("Received notification:");
try
{
Enumeration propertyNames = notif.getPropertyNames();
while (propertyNames.hasMoreElements())
{
String propertyName = (String)propertyNames.nextElement();
System.out.format(" %s: %s\n", propertyName, notif.getObjectProperty(propertyName));
}
}
catch (JMSException e)
{
}
System.out.println("------------------------");
}
});
</programlisting>
</section>
<section>
<title>例子</title>
<para>参见<xref linkend="examples.management-notifications"/>。本例采用了JMS的<literal>
MessageListener</literal>方法从ActiveMQ
服务器接收管理通知。</para>
</section>
</section>
<section id="management.message-counters">
<title>消息计数器</title>
<para>ActiveMQ保存着队列的历史数据而消息计数器可以从服务器上获取这些信息。</para>
<para>这些信息可以显示队列的一些<emphasis>趋势</emphasis>。例如,使用管理接口你可以定期来查询一个队列
的消息数量。但这个数量不足以说明这个队列是否在工作--也许这个队列既没有发送者也没有接收者;也许这个队列
在不停地发送与接收,但是发送消息的速度与接收的速度相等。两咱情况下都会造成消息数在队列中不变,但实际队列
的状态确完全不一样。</para>
<para>消息计数器可以提供队列的更多的信息:</para>
<itemizedlist>
<listitem>
<para><literal>count</literal></para>
<para>从服务器启动时加到队列中的<emphasis></emphasis>消息数。</para>
</listitem>
<listitem>
<para><literal>countDelta</literal></para>
<para><emphasis>上次消息计数器更新</emphasis>后加入到队列的消息数。</para>
</listitem>
<listitem>
<para><literal>depth</literal></para>
<para>队列<emphasis>当前</emphasis>的消息数。</para>
</listitem>
<listitem>
<para><literal>depthDelta</literal></para>
<para><emphasis>上次消息计数器更新</emphasis>后被加入/删除的消息<emphasis>总数</emphasis>
例如,如果<literal>depthDelta</literal><literal>-10</literal>就意谓着有10个消息从
队列中删除了有可能是2个消息加入了但有12个消息删除了</para>
</listitem>
<listitem>
<para><literal>lastAddTimestamp</literal></para>
<para>最后一个消息加入到队列的时间戳。</para>
</listitem>
<listitem>
<para><literal>udpateTimestamp</literal></para>
<para>最后一次消息计数器更新的时间戳。</para>
</listitem>
</itemizedlist>
<section id="configuring.message.counters">
<title>配置消息计数器</title>
<para>默认的消息计数器是关闭的,因为它需要占用一些内存。</para>
<para>要打开消息计数器,编辑<literal>activemq-configuration.xml</literal>文件将其设为<literal>true</literal></para>
<programlisting>
&lt;message-counter-enabled&gt;true&lt;/message-counter-enabled&gt;
</programlisting>
<para>消息计数器会保存队列的历史数据默认是10天。它以一定间隔默认10秒一次对每个队列进行扫描。
如果消息计数器打开,这些参数可以在<literal>activemq-configuration.xml</literal>文件中进行调整:</para>
<programlisting>
&lt;!-- keep history for a week --&gt;
&lt;message-counter-max-day-history&gt;7&lt;/message-counter-max-day-history&gt;
&lt;!-- sample the queues every minute (60000ms) --&gt;
&lt;message-counter-sample-period&gt;60000&lt;/message-counter-sample-period&gt;
</programlisting>
<para>使用管理接口可以获得消息计数器。例如要使用JMX得到一个JMS队列的消息计数器</para>
<programlisting>
// retrieve a connection to ActiveMQ's MBeanServer
MBeanServerConnection mbsc = ...
JMSQueueControlMBean queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc,
on,
JMSQueueControl.class,
false);
// message counters are retrieved as a JSON String
String counters = queueControl.listMessageCounter();
// use the MessageCounterInfo helper class to manipulate message counters more easily
MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);
System.out.format("%s message(s) in the queue (since last sample: %s)\n",
counter.getDepth(),
counter.getDepthDelta());
</programlisting>
</section>
<section>
<title>例子</title>
<para>参见<xref linkend="examples.message-counters"/>。这个例子使用消息计数器来获得一个JMS队列的相关数据。</para>
</section>
</section>
<section>
<title>通过JBoss应用服务器的Admin Console来管理ActiveMQ的资源</title>
<para>通过JBoss应用服务器的Admin Console可以创建与配置ActiveMQ的各种资源。</para>
<para>Admin Console允许你创建各种目标JMS话题与队列和JMS的连接工厂。</para>
<para>登录admin console后你在左边的树中会看到JMS Manager节点。所有ActiveMQ的资源都属于这个节点。在它的下面有JMS Queues、
Topics以及Connection Factories。分别点击它们将会看到相应的资源。下面将解释如何创建并配置它们。</para>
<section>
<title>JMS队列</title>
<para>要创建一个新的JMS队列点击JMS Queues将列出当前的队列。在右边的窗口中有一个“add a new resource“按钮点击这个按钮
并选择默认JMS 队列模板。点击“continue“。填入相应的队列名称与JNDI名称。其它的参数值都给出了合理的默认值通常情况下
不用改动它们。在底部可以配置安全角色,如果你不提供将使用默认的配置。当这个队列成功创建后这些配置将会显示出来。除了队列的名字
和JNDI名字外其它参数都可以在contiguration标签页下进行修改。下面就对它们分别解释。</para>
<para>点击 configuration后你将看到如下显示</para>
<para>
<graphic fileref="images/console1.png" align="center"/>
</para>
<para>name和JNDI name是不能改变的。如果你想改变它们必须重新创建队列。其它选项是关于地址设置与安全设置。
默认的地址设置来自于服务器的配置。如果你通过console修改或创建一个队列那么就会增加一条新的地址设置。有关
地址设置的完整说明参见<xref linkend="queue-attributes.address-settings"/></para>
<para>要删除一个队列只要点击队列名称旁边的“delete“按钮即可。与此队列相关的任何地址设置或安全设置也将被删除。</para>
<para>配置的最后一部分是安全角色。如果在创建时没有给出则默认的安全设置将会显示在屏幕上。如果它们被修改并更新则队列的安全设置
将被更新。关于安全设置参见<xref linkend="security"/></para>
<para>在console中还有一个metrics标签页它显示了队列的各项统计数据如消息计数接收者计数等。</para>
<para>在control标签页中可以对队列进行各种操作比如启动和停止队列对队列中的消息进行列表移动变为过期删除等。
要进行一项操作只要点击相应的按钮然后在出现的提示中输入相应的参数再点击ok按钮即可。操作的結果会显示在屏幕的底部。</para>
</section>
<section>
<title>JMS话题</title>
<para>创建及配置JMS话题几乎与队列的操作是一样的。唯一不同的是这些配置应用于一个代表订阅的队列。</para>
</section>
<section>
<title>JMS连接工厂</title>
<para>JMS连接工厂的创建的操作过程与上述队列或话题的操作一致只是配置具体的参数不同而已。关于连接工厂的参数参见配置索引。</para>
</section>
</section>
</chapter>