主从备份方式
多个代理同时运行,但是只有一个是活动的(主),主挂了,从的会获得接管工作。
有两种主从方式
无共享主从
主机和备机各自拥有自己的消息存储
备机需要连接到主代理,且需要额外的配置用来报告其当前的状态,而主消息代理不需要
这种额外的配置.主机也有一些可选的配置项
所有消息指令(消息,确认,订阅,日志等)都会从主机拷贝到备机上,配置主/备机后确实会在消息处理过程中引入一些额外的开销.
当一个消息生产者发送持久化消息给主机后,消息生产者需要等待主机的回执然后才能发送下一条消息.主机在将消息拷贝到备机上并且等待备机依次处理完消息(这种处理通常是备机将消息存储已进行持久化).备机处理完后,主机便开始处理消息(存储以便持久化消息,然后分发消息给所有对消息感兴趣的消费者),主机成功消息完处理后才会发送回执给消息生产者.
当主机失效后,备机有以下两种选择:
1. 关闭自身 -- 这样,备机的作用就是保存主机失效之前的状态. 在这种情况下,系统管理员可以手工配置备机为新主机,并再配置一个新的消息代理担当备机的角色.
2. 启动其传输连接其并初始化所有网络连接 --这样,备机自动的变成了新主机
当备机担当起主机的角色后,所有使用失效转移连接器的客户端会自动切换连接到新主机上.
对于使用ActiveMQ的JMS客户端来说,默认使用的就是失效转移传输连接器,这种连接器通常
会被配置成既可以连接到主机也可以连接到备机,配置如下所示:
failover://(tcp://masterhost:61616,tcp://slavehost:61616)?randomize=false
以上模式可能存在一些问题,比如在主键和备机之间的连接还没建立,但是消息一经进入主机,那么备机是无法备份到这部分数据的。
为了防止数据没有完全同步,应该先把所有的代理停止,并且把主机的data目录拷贝到备机。
另外,在主机失效后,你还需要配置一个新的备机。无共享主/备机配置应当在你需要保证主机失效后没有消息丢失,且能接受一些停机时间以便在原来备机成为新主机后为应用程序配置新备机时使用.
将一个代理配置为备机很简单.你只需配置收下面参数的masterConnector服务:
remoteURI —代理主机监听的URI
userName—可选的用户名,当主机需要认证时使用
password—可选的密码,当主机需要认证时使用
可选属性
waitForSlave false 如果配置为true,则主机代理在备机连接好之前,步接收任何客户端和网络连接
shutdownOnSlaveFailure false 如果配额为true,则与备机失去连接后,主机代理会自动关闭.这样就保证了备机与主机永远是同步的.
<services>
<masterConnector
remoteURI="tcp://remotehost:62001"
userName="Rob"
password="Davies"
/>
</services>
备机代理和主机代理的transport和network配置成一样的.
可选属性是:shutdownOnMasterFailure属性.当配置这个
属性为启用时,备机主机在主机失效后会安全的关闭,确保消息不会丢失,这样就允许系统管理员手工配置一个新的备机代理
备机属性
shutdownOnMasterFailure false 如果配置为true,则主机失效后,备机代理会自动关闭
备机的配置
<broker masterConnectorURI="tcp://masterhost:62001" shutdownOnMasterFailure="false">
<persistenceAdapter>
<journaledJDBC journalLogFiles="5" dataDirectory="${activemq.base}/data/broker2" />
</persistenceAdapter>
<transportConnectors>
<transportConnector uri="tcp://slavehost:61616"/>
</transportConnectors>
</broker>
需要指定masterConnector
对于最新版本的,该方式已经不推荐了
共享存储主/备机配置.
具有更好的容错。
任一时间仅有一个代理是活动的.使用共享资源存储可以确保在主机代理失效时无需手工干预即可让应用程序从失败状态中恢复.使用共享存储主/备机的另一个好处是对于备机数量没有限制.ActiveMQ可以配置两种方式的共享存储主/备机:关系数据库和基于文件系统的存储.
当使用关系数据库存储消息时,ActiveMQ消息代理会在相关的表上设置一个排他锁以保证
在同一时间只有一个代理可以操作这个表.这是因为代理的状态是由存储机制来维护的并且
这个存储机制被设计成在同一时间只供一个代理使用。
如果你同时运行着的多个代理同时操作数据库,那么只有第一个连接到数据库的代理可以获取那个排他锁.任何其他的代理将等待直到它们获得那个排他锁.等待排他锁的代理被视为备机,因而这种代理不会启动任何的传输练级和网络连接.
你可以同时运行多个代理,但是在同一时间只有一个代理会成为主机代理。如果主机代理失效了,备机代理会获取数据库中的排他锁进而接管主机代理的功能而变成一个新的主机代理.因为这种配置下所有的代理共享同一个数据库存储,所以在新加入或者移除一个代理时步需要收手工修改配置.
<beans>
<!-- Allows us to use system properties as variables in this configuration file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<broker xmlns="http://activemq.apache.org/schema/core">
<destinationPolicy>
<policyMap><policyEntries>
<policyEntry topic="FOO.>">
<dispatchPolicy>
<strictOrderDispatchPolicy />
</dispatchPolicy>
<subscriptionRecoveryPolicy>
<lastImageSubscriptionRecoveryPolicy />
</subscriptionRecoveryPolicy>
</policyEntry>
</policyEntries></policyMap>
</destinationPolicy>
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.base}/activemq-data"/>
<!--
<jdbcPersistenceAdapter dataDirectory="activemq-data" dataSource="#oracle-ds"/>
-->
</persistenceAdapter>
<transportConnectors>
<transportConnector name="default" uri="tcp://localhost:61616"/>
</transportConnectors>
</broker>
<!-- This xbean configuration file supports all the standard spring xml configuration options -->
<!-- Postgres DataSource Sample Setup -->
<!--
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource">
<property name="serverName" value="localhost"/>
<property name="databaseName" value="activemq"/>
<property name="portNumber" value="0"/>
<property name="user" value="activemq"/>
<property name="password" value="activemq"/>
<property name="dataSourceName" value="postgres"/>
<property name="initialConnections" value="1"/>
<property name="maxConnections" value="10"/>
</bean>
-->
<!-- MySql DataSource Sample Setup -->
<!--
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/>
<property name="username" value="activemq"/>
<property name="password" value="activemq"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
-->
<!-- Oracle DataSource Sample Setup -->
<!--
<bean id="oracle-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:AMQDB"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
-->
<!-- Embedded Derby DataSource Sample Setup -->
<!--
<bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource">
<property name="databaseName" value="derbydb"/>
<property name="createDatabase" value="create"/>
</bean>
-->
</beans>
共享文件系统
采用文件锁的方式,需要使用共享文件系统(如,san,nfs,windows的共享目录等)。
共享文件是推荐的方式,比jdbc拥有更好的性能,比无共享拥有更好的容错。
该方案将KahaDB的高吞吐量和使用共享资源的简单易用结合起来.KahaDB仅仅受到底层文件系统性能的限制.唯一的警告是,环境中使用的共享文件系统必须支持分布式文件锁.
<persistenceAdapter>
<kahaDB directory="/sharedFileSystem/sharedBrokerData"/>
</persistenceAdapter>