??xml version="1.0" encoding="utf-8" standalone="yes"?> 作ؓ一U组l事件和订阅感兴那部分信息的一U方法,q个概念在金融市场领域已l流行了一D|间了。设想你有以下两个destinationQ?/p>
订阅者可以明地指定destination的名字来订阅消息Q或者它也可以用wildcards来定义一个分层的模式来匹配它希望订阅的destination。例如: 2Q?Q? Async Sends 2Q?Q? Dispatch Policies 2Q?Q?Q? Strict Order Dispatch Policy consumer1: P1 P2 Q1 P3 Q2 以下是ActiveMQ配置文g的一个例子: 2Q?Q?0 Message Cursors 在缺省情况下QActiveMQ 5.0Ҏ使用的Message Store来决定用何U类型的Message CursorsQ但是你可以Ҏdestination来配|Message Cursors?/p>
对于topicQ可以用的pendingSubscriberPolicy
有vmCursor和fileCursor。可以用的PendingDurableSubscriberMessageStoragePolicy?
vmDurableCursor ?fileDurableSubscriberCursor。以下是ActiveMQ配置文g的一个例子: 对于queueQ可以用的pendingQueuePolicy有vmQueueCursor ?fileQueueCursor。以下是ActiveMQ配置文g的一个例子: 2Q?Q?1 Optimized Acknowledgement 2Q?Q?2 Producer Flow Control 2Q?Q?3 Message Transformation MessageTransformer接口支持Q? 以下是个单的例子Q ? 在consumer的session上设|一个MessageTransformer用于ObjectMessage转换成TextMessageQ如下:
Wildcards用来支持联合的名字分层体p(federated name hierarchiesQ。它不是JMS规范的一部分Q而是ActiveMQ的扩展。ActiveMQ支持以下三种wildcardsQ?/p>
Subscription
Meaning
PRICE.>
Any price for any product on any exchange
PRICE.STOCK.>
Any price for a stock on any exchange
PRICE.STOCK.NASDAQ.*
Any stock price on NASDAQ
PRICE.STOCK.*.IBM
Any IBM stock price on any exchange
ActiveMQ支持以同步(syncQ方式或者异步(asyncQ方式向broker发送消息?使用何种方式对sendҎ的gq有巨大的媄响。对于生产者来_既然延迟是决定吞吐量的重要因素,那么使用异步发送方式会极大地提高系l的性能?br />
ActiveMQ~省使用异步传输方式。但是按照JMS规范Q当在事务外发送持久化消息的时候,ActiveMQ会强制用同步发送方式。在q种情况下,
每一ơ发送都是同步的Q而且d到收到broker的应{。这个应{保证了broker已经成功地将消息持久化,而且不会丢失。但是这样作也严重地影响?
性能?br /> 如果你的pȝ可以容忍量的消息丢失,那么可以在事务外发送持久消息的时候,选择使用异步方式。以下是几种不同的配|方式:
2Q?Q?Q? Round Robin Dispatch Policy
?Q?Q?节介绍qActiveMQ的prefetch机制QActiveMQ的缺省参数是针对处理大量消息时的高性能和高吞吐量而设|的。所以缺?
的prefetch参数比较大,而且~省的dispatch
policies会尝试尽可能快的填满prefetch~冲。然而在有些情况下,例如只有量的消息而且单个消息的处理时间比较长Q那么在~省?
prefetch和dispatch
policies下,q些量的消息L們于被分发C别的consumer上。这样就会因载的不均衡分配而导致处理时间的增加?br /> Round robin dispatch policy会尝试^均分发消息,以下是ActiveMQ配置文g的一个例子:
有时候需要保证不同的topic consumer以相同的序接收消息。通常ActiveMQ会保证topic
consumer以相同的序接收来自同一个producer的消息。然而,׃多线E和异步处理Q不同的topic
consumer可能会以不同的顺序接收来自不同producer的消息。例如有两个producerQ分别是P和Q。差不多是同一旉内,P发送了
P1、P2和P3三个消息QQ发送了Q1和Q2两个消息。两个不同的consumer可能会以以下序接收到消息:
consumer2: P1 Q1 Q2 P2 P3
Strict order dispatch policy 会保证每个topic
consumer会以相同的顺序接收消息,代h是性能上的损失。以下是采用了strict order dispatch
policy后,两个不同的consumer可能以以下的序接收消息Q?br /> consumer1: P1 P2 Q1 P3 Q2
consumer2: P1 P2 Q1 P3 Q2
当producer发送的持久化消息到达broker之后Qbroker首先会把它保存在持久存储中。接下来Q如果发现当前有z跃的consumerQ?
且这个consumer消费消息的速度能跟上producer生消息的速度Q那么ActiveMQ会直接把消息传递给broker内部跟这?
consumer兌的dispatch
queueQ如果当前没有活跃的consumer或者consumer消费消息的速度跟不上producer生消息的速度Q那么ActiveMQ会?
Pending Message Cursors保存Ҏ息的引用。在需要的时候,Pending Message
Cursors把消息引用传递给broker内部跟这个consumer兌的dispatch queue。以下是两种Pending Message
CursorsQ?/p>
ActiveMQ~省支持扚w认消息。由于批量确认会提高性能Q因此这是缺省的认方式。如果希望在应用E序中禁止经q优化的认方式Q那么可以采用如下方法:
同步发送消息的producer会自动用producer flow control
Q对于异步发送消息的producerQ要使用producer flow
controlQ你先要为connection配置一个ProducerWindowSize参数Q如下:
有时候需要在JMS provider内部q行message的{换。从4.2版本PActiveMQ 提供了一个MessageTransformer 接口用于q行消息转换Q如下:
]]>
ActiveMQ包含了很多功能强大的Ҏ,下面要介l其中的几个?br />2Q?Q? Exclusive Consumer
Queue中的消息是按照顺序被分发到consumers的。然而,当你有多个consumers同时从相同的queue中提取消息时Q你失去这个保
证。因些消息是被多个线Eƈ发的处理。有的时候,保证消息按照序处理是很重要的。例如,你可能不希望在插入订单操作结束之前执行更新这个订单的?
作?br /> ActiveMQ?.x版本起开始支持Exclusive Consumer Q或者说Exclusive QueuesQ?
Broker会从多个consumers中挑选一个consumer来处理queue中所有的消息Q从而保证了消息的有序处理。如果这个consumer
失效Q那么broker会自动切换到其它的consumer?br /> 可以通过Destination Options 来创Z个Exclusive ConsumerQ如下:
2Q?Q? Message Groups
用Apache官方文档的话_Message Groups rockQ它是Exclusive
Consumer功能的增强。逻辑上,Message Groups 可以看成是一Uƈ发的Exclusive
Consumer。跟所有的消息都由唯一的consumer处理不同QJMS 消息属性JMSXGroupID 被用来区分message
group。Message GroupsҎ保证所有具有相同JMSXGroupID
的消息会被分发到相同的consumerQ只要这个consumer保持activeQ。另外一斚wQMessage
GroupsҎ也是一U负载均衡的机制?br />
在一个消息被分发到consumer之前Qbroker首先查消息JMSXGroupID属性。如果存在,那么broker
会检查是否有某个consumer拥有q个message
group。如果没有,那么broker会选择一个consumerQƈ它兌到这个message
group。此后,q个consumer会接收这个message group的所有消息,直到Q?/p>
?.1版本开始,ActiveMQ支持一个布字DJMSXGroupFirstForConsumer 。当某个message group的第一个消息被发送到consumer的时候,q个字段被设|。如果客户用failover transportq接到broker。在׃|络问题{造成客户重新q接到broker的时候,相同message group的消息可能会被分发到不同与之前的consumerQ因此JMSXGroupFirstForConsumer字段也会被重新设|。?
以下是用message groups的例子:
2Q?Q? Pending Message Limit Strategy
首先要介l一下prefetch机制。ActiveMQ通过prefetch机制来提高性能Q这意味q客L的内存里可能会缓存一定数量的消息。缓存消
息的数量由prefetch limit来控制。当某个consumer的prefetch
buffer已经辑ֈ上限Q那么broker不会再向consumer分发消息Q直到consumer向broker发送消息的认。可以通过?
ActiveMQConnectionFactory或者ActiveMQConnection上设|ActiveMQPrefetchPolicy对象
来配|prefetch policy。也可以通过connection options或者destination options来配|。例如:
tcp://localhost:61616?jms.prefetchPolicy.all=50
tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1
queue = new ActiveMQQueue("TEST.QUEUE?consumer.prefetchSize=10");
prefetch size的缺省值如下:
慢消费者会在非持久的topics上导致问题:一旦消息积压v来,会导致broker把大量消息保存在内存中,broker也会因此而变慢。未? ActiveMQ可能会实现磁盘缓存,但是q也q是会存在性能问题。目前ActiveMQ使用Pending Message Limit Strategy来解册个问题。除了prefetch buffer之外Q你q要配置~存消息的上限,过q个上限后,新消息到来时会丢弃旧消息。通过在配|文件的destination map中配|PendingMessageLimitStrategyQ可以ؓ不用的topic namespace配置不同的策略。目前有以下两种Q?/p>
在以上两U方式中Q如果设|?意味着除了prefetch之外不再~存消息Q如果设|?1意味着止丢弃消息。?
此外Q你q可以配|消息的丢弃{略Q目前有以下两种Q?/p>
以下是个ActiveMQ配置文g的例子:
2Q?Q? Composite Destinations
?.1版本? ActiveMQ支持composite destinations。它允许用一个虚拟的destination
代表多个destinations。例如你可以通过composite
destinations在一个操作中同时?2个queue发送消息。在composite
destinations中,多个destination之间采用","分割。例如:
如果你希望用不同类型的destinationQ那么需要加上前~如queue:// 或topic://Q例如:
以下是ActiveMQ配置文gq行配置的一个例子:
可以在{发前Q先通过JMS Selector判断一个消息是否需要{发,例如Q?/p>
2Q?Q? Mirrored Queues
每个queue中的消息只能被一个consumer消费。然而,有时候你可能希望能够监视生者和消费者之间的消息。你可以通过使用Virtual
Destinations 来徏立一个virtual queue 来把消息转发到多个queues中。但?
为系l中每个queue都进行如此的配置可能会很ȝ?
ActiveMQ支持Mirrored
Queues。Broker会把发送到某个queue的所有消息{发到一个名U类似的topicQ因此监控程序可以订阅这个mirrored queue
topic。ؓ了启用Mirrored
QueuesQ首先要BrokerService的useMirroredQueues属性设|成trueQ然后可以通过
destinationInterceptors讄其它属性,如mirror
topic的前~Q缺省是"VirtualTopic.Mirror."。以下是ActiveMQ配置文g的一个例子:
2Q?Q? JAAS Authentication Plugin
JAAS Authentication
Plugin依赖标准的JAAS机制来实现认证。通常情况下,你需要通过讄java.security.auth.login.configpȝ属性来
配置login modules的配|文件。如果没有指定这个系l属性,那么JAAS Authentication
Plugin会缺省用login.config作ؓ文g名。以下是一个login.config文g的例子:
activemq-domain {
org.apache.activemq.jaas.PropertiesLoginModule required
debug=true
org.apache.activemq.jaas.properties.user="users.properties"
org.apache.activemq.jaas.properties.group="groups.properties";
};
q个login.config文g中设|了两个属性:org.apache.activemq.jaas.properties.user?
org.apache.activemq.jaas.properties.group分别用来指向user.properties?
group.properties文g。需要注意的是,PropertiesLoginModule使用本地文g的查找方式,而且查找旉用的base
directory是login.config文g所在的目录。因此这个login.config说明user.properties?
group.properties文g存放在跟login.config文g相同的目录里?br /> 以下是ActiveMQ配置的一个例子:
Z以上的配|,在JAAS的LoginContext中会使用activemq-domain中配|的PropertiesLoginModule来进行登陆?br /> ActiveMQ JAASq支持LDAPLoginModule、CertificateLoginModule、TextFileCertificateLoginModule{login module?/p>
2Q?Q? Custom Authentication Implementation
可以通过~码的方式ؓActiveMQ增加认证功能。例如编写一个类l承自XBeanBrokerService?
在这个配|文件中增加了一个namespace authQ用于指向之前编写的哪个cR同时ؓSimpleAuthBroker注入了两个属性值user和passwordQ因此在? SimpleAuthBroker改写的addInterceptorsҎ里,可以使用q两个属性进行认证了。ActiveMQ提供? SimpleAuthenticationBrokercȝ承自BrokerFilterQ可以简单的看成是Broker的AdaptorQ,它的构造函 C的两个Map分别是userPasswords和userGroups?SimpleAuthenticationBroker? addConnectionҎ中用userPasswordsq行认证Q同时会把userGroups的信息保存到 ConnectionContext??/p>
2Q?Q? Authorization Plugin
可以通过Authorization Plugin证后的用h权,以下ActiveMQ配置文g的一个例子:
那么l过一D|间后可能会报出如下错误:
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!
Apache官方文档_此bug已经被修正,预定?.1.0版本上体现?/p>
2Q?Q? Broker clusters
一个常见的场景是有多个JMS
brokerQ有一个客戯接到其中一个broker。如果这个broker失效Q那么客户会自动重新q接到其它的broker。在ActiveMQ中
用failover:// 协议来实现这个功能。ActiveMQ3.x版本的reliable://协议已经变更为failover://?br />
如果某个|络上有多个brokers而且客户使用静态发玎ͼ使用Static Transport或Failover
TransportQ或动态发玎ͼ使用Discovery
TransportQ,那么客户可以Ҏ地在某个broker失效的情况下切换到其它的brokers。然而,stand alone
brokersq不了解其它brokers上的consumersQ也是说如果某个broker上没有consumersQ那么这个broker上的?
息可能会因得不到处理而积压v来。目前的解决Ҏ是用Network of
brokersQ以便在broker之间存储转发消息。ActiveMQ在未来会有更好的Ҏ,用来在客L处理q个问题?br />
从ActiveMQ1.1版本PActiveMQ支持networks of
brokers。它支持分布式的queues和topics。一个broker会相同对待所有的订阅QsubscriptionQ:不管他们是来自本地的
客户q接Q还是来自远EbrokerQ它都会递送有关的消息拯到每个订阅。远Ebroker得到q个消息拯后,会依ơ把它递送到其内部的本地q接上?
有两U方式配|Network of brokersQ一U是使用static transportQ如下:
Property | Default Value | Description |
name | bridge | name of the network - for more than one network connector between the same two brokers - use different names |
dynamicOnly | false | if true, only forward messages if a consumer is active on the connected broker |
decreaseNetworkConsumerPriority | false | decrease the priority for dispatching to a Queue consumer the further away it is (in network hops) from the producer |
networkTTL | 1 | the number of brokers in the network that messages and subscriptions can pass through |
conduitSubscriptions | true | multiple consumers subscribing to the same destination are treated as one consumer by the network |
excludedDestinations | empty | destinations matching this list won't be forwarded across the network |
dynamicallyIncludedDestinations | empty | 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 |
staticallyIncludedDestinations | empty | destinations that match will always be passed across the network - even if no consumers have ever registered an interest |
duplex | false | 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. |
关于conduitSubscriptions属性,q里E稍说明一下。设x两个brokersQ分别是brokerA和brokerBQ它们之间用 forwarding bridgeq接。有一个consumerq接到brokerAq订阅queueQQ.TEST。有两个consumersq接到brokerBQ也是订 阅queueQQ.TEST。这三个consumers有相同的优先U。然后启动一个producerQ它发送了30条消息到brokerA。如? conduitSubscriptions=trueQ那么brokerA上的consumer会得?5条消息, 另外15条消息会发送给brokerB。此时负载ƈ不均衡,因ؓ此时brokerAbrokerB上的两个consumers视ؓ一个;如果 conduitSubscriptions=falseQ那么每个consumer上都会收?0条消息。以下是关于NetworkConnector? 性的一个例子:
2Q?Q? Master Slave
在一个网l内q行多个brokers或者stand alone
brokers时存在一个问题,q就是消息在物理上只被一个broker持有Q因此当某个broker失效Q那么你只能{待直到它重启后Q这?
broker上的消息才能够被l箋发送(如果没有讄持久化,那么在这U情况下Q消息将会丢失)。Master Slave
背后的想法是Q消息被复制到slave brokerQ因此即使master broker遇到了像g故障之类的错误,你也可以立即切换到slave
broker而不丢失M消息?br /> Master Slave是目前ActiveMQ推荐的高可靠性和定w的解x案。以下是几种不同的类型:
Master Slave Type | Requirements | Pros | Cons |
Pure Master Slave | None | No central point of failure | Requires manual restart to bring back a failed master and can only support 1 slave |
Shared File System Master Slave | A Shared File system such as a SAN | Run as many slaves as required. Automatic recovery of old masters | Requires shared file system |
JDBC Master Slave | A Shared database | Run as many slaves as required. Automatic recovery of old masters | Requires a shared database. Also relatively slow as it cannot use the high performance journal |
2Q?Q?Q? Pure Master Slave
Pure Master Slave的工作方式如下:
Pure Master Slaveh以下限制Q?/p>
Master broker不需要特D的配置。Slave broker需要进行以下配|?/p>
其中的masterConnectorURI用于指向master brokerQshutdownOnMasterFailure用于指定slave broker在master broker失效的时候是否需要停止。此外,也可以用如下配|:
需要注意的是,W者认为ActiveMQ5.0版本的Pure Master Slave仍然不够E_?
2Q?Q?Q? Shared File System Master Slave
如果你用SAN或者共享文件系l,那么你可以用Shared File System Master
Slave。基本上Q你可以q行多个brokerQ这些broker׃n数据目录。当W一个broker得到文g上的排他锁之后,其它的broker便会
在@环中{待获得q把锁。客L使用failover transport来连接到可用的broker。当master
broker失效的时候会释放q把锁,q时候其中一个slave broker会得到这把锁从而成为master
broker。以下是ActiveMQ配置的一个例子:
2Q?Q?Q? JDBC Master Slave
JDBC Master Slave的工作原理跟Shared File System Master SlavecMQ只是采用了数据库作为持久化存储。以下是ActiveMQ配置的一个例子:
需要注意的是,如果你用MySQL数据库,需要首先执行以下三条语句:QApache官方文档_此bug已经被修正,预定?.1.0版本上体玎ͼ
Property name | Default value | Comments |
directory | activemq-data | the path to the directory to use to store the message store data and log files |
useNIO | true | use NIO to write messages to the data logs |
syncOnWrite | false | sync every write to disk |
maxFileLength | 32mb | a hint to set the maximum size of the message data logs |
persistentIndex | true | use a persistent index for the message logs. If this is false, an in-memory structure is maintained |
maxCheckpointMessageAddSize | 4kb | the maximum number of messages to keep in a transaction before automatically committing |
cleanupInterval | 30000 | time (ms) before checking for a discarding/moving message data logs that are no longer used |
indexBinSize | 1024 | default number of bins used by the index. The bigger the bin size - the better the relative performance of the index |
indexKeySize | 96 | the size of the index key - the key is the message id |
indexPageSize | 16kb | the size of the index page - the bigger the page - the better the write performance of the index |
directoryArchive | archive | the path to the directory to use to store discarded data logs |
archiveDataLogs | false | if true data logs are moved to the archive directory instead of being deleted |
2Q?Q? Kaha Persistence
Kaha Persistence 是一个专门针Ҏ息持久化的解x案。它对典型的消息使用模式q行了优化。在Kaha中,数据被追加到data logs中。当不再需要log文g中的数据的时候,log文g会被丢弃。以下是光|的一个例子:
2Q?Q? JDBC Persistence
目前支持的数据库有Apache Derby, Axion, DB2, HSQL, Informix, MaxDB, MySQL, Oracle, Postgresql, SQLServer, Sybase?br /> 如果你用的数据库不被支持,那么可以调整StatementProvider 来保证用正的SQL方言Qflavour of SQLQ。通常l大多数数据库支持以下adaptorQ?
也可以在配置文g中直接指定JDBC adaptorQ例如:
需要注意的是,如果使用MySQLQ那么需要设|relaxAutoCommit 标志为true?/p>
2Q?Q? Disable Persistence
以下是其配置的一个例子:
2Q?Q? VM Transport
VM transport允许在VM内部通信Q从而避免了|络传输的开销。这时候采用的q接不是socketq接Q而是直接地方法调用?
W一个创建VM q接的客户会启动一个embed VM brokerQ接下来所有用相同的broker
name的VMq接都会使用q个broker。当q个broker上所有的q接都关闭的时候,q个broker也会自动关闭?br /> 以下是配|语法:
vm://brokerName?transportOptions
例如Qvm://broker1?marshal=false&broker.persistent=false
Transport Options的可选值如下:
Option Name | Default Value | Description |
Marshal | false | If true, forces each command sent over the transport to be marshlled and unmarshlled using a WireFormat |
wireFormat | default | The name of the WireFormat to use |
wireFormat.* | All the properties with this prefix are used to configure the wireFormat | |
create | true | If the broker should be created on demand if it does not allready exist. Only supported in ActiveMQ 4.1 |
broker.* | All the properties with this prefix are used to configure the broker. See Configuring Wire Formats for more information |
以下是高U配|语法:
vm:(broker:(tcp://localhost)?brokerOptions)?transportOptions
vm:broker:(tcp://localhost)?brokerOptions
例如Qvm:(broker:(tcp://localhost:6000)?persistent=false)?marshal=false
Transport Options的可选值如下:
Option Name | Default Value | Description |
marshal | false | If true, forces each command sent over the transport to be marshlled and unmarshlled using a WireFormat |
wireFormat | default | The name of the WireFormat to use |
wireFormat.* | All the properties with this prefix are used to configure the wireFormat |
使用配置文g的配|语法:
vm://localhost?brokerConfig=xbean:activemq.xml
例如Qvm:// localhost?brokerConfig=xbean:com/test/activemq.xml
使用Spring的配|:
如果persistent是trueQ那么ActiveMQ会在当前目录下创Z个缺省值是activemq-data的目录用于持久化保存数据。需要注 意的是,如果E序中启动了多个不同名字的VM brokerQ那么可能会有如下警告:Failed to start jmx connector: Cannot bind to URL [rmi://localhost:1099/jmxrmi]: javax.naming.NameAlreadyBoundException…可以通过在transportOptions中追? broker.useJmx=false来禁用JMX来避免这个警告?/p>
2Q?Q? TCP Transport
TCP transport 允许客户端通过TCP socketq接到远E的broker。以下是配置语法Q?br /> tcp://hostname:port?transportOptions
Transport Options的可选值如下:
Option Name | Default Value | Description |
minmumWireFormatVersion | 0 | The minimum version wireformat that is allowed |
trace | false | Causes all commands that are sent over the transport to be logged |
useLocalHost | true | When true, it causes the local machines name to resolve to "localhost". |
socketBufferSize | 64 * 1024 | Sets the socket buffer size in bytes |
soTimeout | 0 | sets the socket timeout in milliseconds |
connectionTimeout | 30000 | 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. |
wireFormat | default | The name of the WireFormat to use |
wireFormat.* | All the properties with this prefix are used to configure the wireFormat. See Configuring Wire Formats for more information |
例如Qtcp://localhost:61616?trace=false
2Q?Q? Failover Transport
Failover
Transport是一U重新连接的机制Q它工作于其它transport的上层,用于建立可靠的传输。它的配|语法允许制定Q意多个复合的URI?
Failover
transport会自动选择其中的一个URI来尝试徏立连接。如果没有成功,那么会选择一个其它的URI来徏立一个新的连接。以下是配置语法Q?br /> failover:(uri1,...,uriN)?transportOptions
failover:uri1,...,uriN
Transport Options的可选值如下:
Option Name | D efault Value | Description |
initialReconnectDelay | 10 | How long to wait before the first reconnect attempt (in ms) |
maxReconnectDelay | 30000 | The maximum amount of time we ever wait between reconnect attempts (in ms) |
useExponentialBackOff | true | Should an exponential backoff be used between reconnect attempts |
backOffMultiplier | 2 | The exponent used in the exponential backoff attempts |
maxReconnectAttempts | 0 | If not 0, then this is the maximum number of reconnect attempts before an error is sent back to the client |
randomize | true | use a random algorithm to choose the URI to use for reconnect from the list provided |
backup | false | initialize and hold a second transport connection - to enable fast failover |
例如Qfailover:(tcp://localhost:61616,tcp://remotehost:61616)?initialReconnectDelay=100
2Q?Q? Discovery transport
Discovery transport是可靠的tranport。它使用Discovery transport来定位用来连接的URI列表。以下是配置语法Q?br /> discovery:(discoveryAgentURI)?transportOptions
discovery:discoveryAgentURI
Transport Options的可选值如下:
Option Name | Default Value | Description |
initialReconnectDelay | 10 | How long to wait before the first reconnect attempt |
maxReconnectDelay | 30000 | The maximum amount of time we ever wait between reconnect attempts |
useExponentialBackOff | true | Should an exponential backoff be used btween reconnect attempts |
backOffMultiplier | 2 | The exponent used in the exponential backoff attempts |
maxReconnectAttempts | 0 | If not 0, then this is the maximum number of reconnect attempts before an error is sent back to the client |
例如Qdiscovery:(multicast://default)?initialReconnectDelay=100
Z使用Discovery来发现brokerQ需要ؓbroker启用discovery agent?以下是XML配置文g中的一个例子:
在用Failover Transport或Discovery transport{能够自动重q的transport的时候,需要注意的是:设想有两个brokerQ它们都启用AMQ Message Store作ؓ持久化存储,有一个producer和一个consumerq接到某个queue。当因其中一个broker失效时而切换到另一? broker的时候,如果失效的broker的queue中还有未被consumer消费的消息,那么q个queue里的消息仍然滞留在失效broker 的中Q直到失效的broker被修复ƈ重新切换回这个被修复的broker后,之前被保留的消息才会被consumer消费掉。如果被处理的消息有时序? Ӟ那么应用E序需要处理这个问题。另外也可以通过ActiveMQ集群来解册个问题?/p>
在transport重连的时候,可以在connection上注册TransportListener来获得回调,例如Q?/p>
1 JMS
在介lActiveMQ之前Q首先简要介l一下JMS规范?br />1Q? JMS的基本构?br />1Q?Q? q接工厂
q接工厂是客L来创接的对象Q例如ActiveMQ提供的ActiveMQConnectionFactory?/p>
1Q?Q? q接
JMS Connection装了客户与JMS提供者之间的一个虚拟的q接?/p>
1Q?Q? 会话
JMS Session是生产和消费消息的一个单U程上下文。会话用于创建消息生产者(producerQ、消息消费者(consumerQ和消息QmessageQ等。会话提供了一个事务性的上下文,在这个上下文中,一l发送和接收被组合到了一个原子操作中?/p>
1Q?Q? 目的?br /> 目的地是客户用来指定它生产的消息的目标和它消费的消息的来源的对象。JMS1.0.2规范中定义了两种消息传递域Q点对点QPTPQ消息传递域和发?订阅消息传递域?br />点对Ҏ息传递域的特点如下:
发布/订阅消息传递域的特点如下:
在点对点消息传递域中,目的地被成ؓ队列QqueueQ;在发?订阅消息传递域中,目的地被成ؓ主题QtopicQ?/p>
1Q?Q? 消息生?br /> 消息生者是׃话创建的一个对象,用于把消息发送到一个目的地?/p>
1Q?Q? 消息消费?br /> 消息消费者是׃话创建的一个对象,它用于接收发送到目的地的消息。消息的消费可以采用以下两种Ҏ之一Q?/p>
1Q?Q? 消息
JMS消息׃下三部分l成Q?/p>
1Q? JMS的可靠性机?br />1Q?Q? 认
JMS消息只有在被认之后Q才认ؓ已经被成功地消费了。消息的成功消费通常包含三个阶段Q客h收消息、客户处理消息和消息被确认?br /> 在事务性会话中Q当一个事务被提交的时候,认自动发生。在非事务性会话中Q消息何时被认取决于创Z话时的应{模式(acknowledgement modeQ。该参数有以下三个可选|
1Q?Q? 持久?br /> JMS 支持以下两种消息提交模式Q?/p>
1Q?Q? 优先U?br /> 可以使用消息优先U来指示JMS provider首先提交紧急的消息。优先?0个别,?Q最低)?Q最高)。如果不指定优先U,默认U别?。需要注意的是,JMS providerq不一定保证按照优先的顺序提交消息?/p>
1Q?Q? 消息q期
可以讄消息在一定时间后q期Q默认是怸q期?/p>
1Q?Q? 临时目的?br /> 可以通过会话上的createTemporaryQueueҎ和createTemporaryTopicҎ来创Z时目的地。它们的存在旉只限于创建它们的q接所保持的时间。只有创临时目的地的q接上的消息消费者才能够从时目的地中提取消息?/p>
1Q?Q? 持久订阅
首先消息生者必M用PERSISTENT提交消息。客户可以通过会话上的createDurableSubscriberҎ来创Z个持久订阅,该方法的W一个参数必L一个topic。第二个参数是订阅的名称?br />
JMS
provider会存储发布到持久订阅对应的topic上的消息。如果最初创建持久订阅的客户或者Q何其它客户用相同的q接工厂和连接的客户ID、相?
的主题和相同的订阅名再次调用会话上的createDurableSubscriberҎQ那么该持久订阅׃被激zRJMS
provider会象客户发送客户处于非Ȁzȝ态时所发布的消息?br /> 持久订阅在某个时d能有一个激zȝ订阅者。持久订阅在创徏之后会一直保留,直到应用E序调用会话上的unsubscribeҎ?/p>
1Q?Q? 本地事务
在一个JMS客户端,可以使用本地事务来组合消息的发送和接收。JMS
Session接口提供了commit和rollbackҎ。事务提交意味着生的所有消息被发送,消费的所有消息被认Q事务回滚意味着生的所有消
息被销毁,消费的所有消息被恢复q新提交,除非它们已经q期?br /> 事务性的会话L牉|C务处理中Qcommit或rollbackҎ一旦被调用Q一个事务就l束了,而另一个事务被开始。关闭事务性会话将回滚其中的事务?br />需要注意的是,如果使用h/回复机制Q即发送一个消息,同时希望在同一个事务中{待接收该消息的回复Q那么程序将被挂P因ؓ知道事务提交Q发送操作才会真正执行?br /> 需要注意的q有一个,消息的生产和消费不能包含在同一个事务中?/p>
1Q? JMS 规范的变q?br /> JMS的最新版本的?.1。它和同1.0.2版本之间最大的差别是,JMS1.1通过l一的消息传递域化了消息传递。这不仅化了JMS APIQ也有利于开发h员灵z选择消息传递域Q同时也有助于程序的重用和维护?br />以下是不同消息传递域的相应接口:
JMS 公共 | 点对点域 | 发布/订阅?/strong> |
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Destination | Queue | Topic |
Session | QueueSession | TopicSession |
MessageProducer | QueueSender | TopicPublisher |
MessageConsumer | QueueReceiver | TopicSubscriber |
2 ActiveMQ
2Q? Broker
2Q?Q? Running Broker
ActiveMQ5.0 的二q制发布包中bin目录中包含一个名为activemq的脚本,直接q行q个脚本可以启动一个broker?br /> 此外也可以通过Broker Configuration URI或Broker XBean URI对brokerq行配置Q以下是一些命令行参数的例子:
Example
|
Description
|
activemq |
Runs a broker using the default 'xbean:activemq.xml' as the broker configuration file. |
activemq xbean:myconfig.xml |
Runs a broker using the file myconfig.xml as the broker configuration file that is located in the classpath. |
activemq xbean:file:./conf/broker1.xml |
Runs
a broker using the file broker1.xml as the broker configuration file
that is located in the relative file path ./conf/broker1.xml |
activemq xbean:file:C:/ActiveMQ/conf/broker2.xml |
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 |
activemq broker:(tcp://localhost:61616, tcp://localhost:5000)?useJmx=true |
Runs a broker with two transport connectors and JMX enabled. |
activemq broker:(tcp://localhost:61616, network:tcp://localhost:5000)?persistent=false |
Runs a broker with 1 transport connector and 1 network connector with persistence disabled. |
2Q?Q? Embedded Broker
可以通过在应用程序中以编码的方式启动brokerQ例如:
URI scheme | Example | Description |
xbean: | xbean:activemq.xml | 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 |
file: | file:foo/bar/activemq.xml | Loads the given file (in this example foo/bar/activemq.xml) as the Xml Configuration |
broker: | broker:tcp://localhost:61616 | Uses the Broker Configuration URI to configure the broker |
当用XBean的配|方式的时候,需要指定一个xml配置文gQ例如:
2Q?Q? Monitoring Broker
2Q?Q?Q? JMX
在用JMX监控broker之前Q首先要启用broker的JMX监控功能Q例如在配置文g中设|useJmx="true"Q如下:
在jconsole的MBeans标签中,可以查看详细信息Q也可以执行相应的operation。需要注意的是,在jconsoleq接到broker 的时候,q不需要输入用户名和密码,如果q存在潜在的安全问题Q那么就需要ؓJMX Connector配置密码保护Q需要?.5以上版本的JDKQ。 ?
首先要禁止ActiveMQ创徏自己的connectorQ例如:
conf/jmx.passwordQ?br /># The "monitorRole" role has password "abc123".
# The "controlRole" role has password "abcd1234".
monitorRole abc123
controlRole abcd1234
然后修改ActiveMQ的bin目录下activemq的启动脚本,查找包含"SUNJMX="的一行如下:
REM
set SUNJMX=-Dcom.sun.management.jmxremote.port=1616
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
把它替换?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
最后重启ActiveMQ和jconsoleQ这时候需要强制login。如果在启动activemq的过E中出现以下错误Q那么需要ؓq个文g增加讉K
控制。Windowsq_上的具体解决Ҏ请参考如下网址Qhttp://java.sun.com/j2se/1.5.0/docs/guide
/management/security-windows.html
Error: Password file read access must be restricted: D:\apache-activemq-5.0.0\bin\../conf/jmx.password
2Q?Q?Q? Web Console
Web Console被集成到了ActiveMQ的二q制发布包中Q因此缺省访问http://localhost:8161/admin卛_讉KWeb Console?br /> 在配|文件中Q可以通过修改nioConnector的port属性来修改Web console的缺省端口:
Z安全性或者可靠性的考虑QWeb Console 可以被部|到不同于ActiveMQ的进E中。例如把activemq-web-console.war部vC个单独的web容器? QTomcatQJetty{)。在ActiveMQ5.0的二q制发布包中不包含activemq-web-console.warQ因此需要下? ActiveMQ的源码,然后q入?{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目录中,q命名成activemq-web-console.war?/p>
需要注意的是,要将activemq-all-5.0.0.jar拯到WEB-INF\lib目录中(可能q需要拷贝jms.jarQ。还要ؓTomcat讄以下五个pȝ属性(修改catalina.bat文gQ:
set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.type="properties"
set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jms.url="tcp://localhost:61616"
set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.url="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"
set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.role=""
set JAVA_OPTS=%JAVA_OPTS% -Dwebconsole.jmx.password=""
如果JMX没有配置密码保护Q那么webconsole.jmx.role和webconsole.jmx.password讄?"卛_。如? broker被配|成了Master/Slave模式Q那么可以配|成使用failover transportQ例如:
-Dwebconsole.jms.url=failover:(tcp://serverA:61616,tcp://serverB:61616)
Z说一下,׃webconsole.type 属性是propertiesQ因此实际上起作用的Web Console的配|文件是WEB-INF/ webconsole-properties.xml。最后启动被监控的ActiveMQQ访问http://localhost:8080 /activemq-web-console/Q查看显C是否正常?
2Q?Q?Q? Advisory Message
ActiveMQ 支持Advisory MessagesQ它允许你通过标准的JMS 消息来监控系l。目前的Advisory Messages支持Q?
Advisory Messages可以被想象成某种的管理通道Q通过它你可以得到关于JMS provider、producers、consumers和destinations的信息。Advisory topics都用ActiveMQ.Advisory.q个前缀Q以下是目前支持的topicsQ?
Client based advisories
Advisory Topics | Description |
ActiveMQ.Advisory.Connection | Connection start & stop messages |
ActiveMQ.Advisory.Producer.Queue | Producer start & stop messages on a Queue |
ActiveMQ.Advisory.Producer.Topic | Producer start & stop messages on a Topic |
ActiveMQ.Advisory.Consumer.Queue | Consumer start & stop messages on a Queue |
ActiveMQ.Advisory.Consumer.Topic | Consumer start & stop messages on a Topic |
在消费者启?/span>/停止?/span>Advisory Messages的消息头中有?/span>consumerCount属性,他用来指明目?/span>desination上活跃的consumer的数量?/span>
Advisory Topics | Description |
ActiveMQ.Advisory.Queue | Queue create & destroy |
ActiveMQ.Advisory.Topic | Topic create & destroy |
ActiveMQ.Advisory.TempQueue | Temporary Queue create & destroy |
ActiveMQ.Advisory.TempTopic | Temporary Topic create & destroy |
ActiveMQ.Advisory.Expired.Queue | Expired messages on a Queue |
ActiveMQ.Advisory.Expired.Topic | Expired messages on a Topic |
ActiveMQ.Advisory.NoConsumer.Queue | No consumer is available to process messages being sent on a Queue |
ActiveMQ.Advisory.NoConsumer.Topic | No consumer is available to process messages being sent on a Topic |
以上的这些destnations都可以用来作为前~Q在其后面追加其它的重要信息Q例如topic、queue、clientID? producderID和consumerID{。这令你可以利用Wildcards ?Selectors 来过滤Advisory MessagesQ关于Wildcard和Selector会在E后介绍Q?/p>
例如Q如果你希望订阅FOO.BARq个queue上Consumer的start/stop的消息,那么可以订阅 ActiveMQ.Advisory.Consumer.Queue.FOO.BARQ如果希望订阅所有queue上的start/stop消息Q那么可 以订阅ActiveMQ.Advisory.Consumer.Queue.>Q如果希望订阅所有queue或者topic上的 start/stop消息Q那么可以订阅ActiveMQ.Advisory.Consumer. >?/p>
org.apache.activemq.advisory.AdvisorySupportcM有如下的helper methodsQ用来在E序中得到advisory destination objects?/p>
以下是段使用Advisory Messages的程序代码:
2Q?Q?Q? Command Agent
在介lCommand Agent前首先简要介l一下XMPP(Jabber)协议QXMPP是一U基于XML的即旉信协议Q它由Jabber软g基金会开发。在配置文g中通过增加transportConnector来支持XMPP协议Q?
推荐XMPP客户端Spark(http://www.igniterealtime.org/)?
?.2版本PActiveMQ支持Command Agent。在配置文g中,通过讄commandAgent来启用Command AgentQ?/p>
2Q?Q?Q? Visualization plugin
ActiveMQ支持以broker插g的Ş式生成DOT文g(可以用agrviewer来查?Q以图表的方式描qconnections、sessions、producers、consumers、destinations{信息。配|方式如下:
需要注意的是,W者认为ActiveMQ5.0版本的Visualization Plugin不E_Q存在诸多问题。例如:如果使用connectionDotFilePluginQ那么brokerName必须? localhostQ如果用destinationDotFilePlugin可能会导致ArrayStoreException?