activemq-集群和主从模式 学习笔记

activemq主从模式与集群

三种masterslave模式

三种主从模式

主从方式 要求 性能
共享文件系统 要求SAN网络共享存储
JDBC主从方式 共享数据库 速度不如日志快
复制的LevelDB zookeeper服务器 速度快

共享文件系统配置
多个broker争夺共享文件锁,取得文件锁的成为master

<persistenceAdapter>
  <kahaDB directory="/sharedFileSystem/sharedBrokerData"/>
persistenceAdapter>

or

<persistenceAdapter>
  <levelDB directory="/sharedFileSystem/sharedBrokerData"/>
persistenceAdapter>

or

<persistenceAdapter>
  <amqPersistenceAdapter directory="/sharedFileSystem/sharedBrokerData"/>
persistenceAdapter>
<broker xmlns="http://activemq.apache.org/schema/core"
dataDirectory="/some/location"
brokerName="mmuserb2" useJmx="true" advisorySupport="false"
persistent="true" deleteAllMessagesOnStartup="false"
useShutdownHook="false" schedulerSupport="true">

JDBC主从方式
跟共享文件系统的方式类似,但是更可靠,速度上最慢

<beans>
  
  <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>

   
  

  <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>

beans>

可复制的LevelDB存储(zooKeeper主从模式推荐模式)
从一系列的broker中取出一个broker作为master,从master的broker同步更新的数据到所有的slave broker。对于N个的broker,同步复制(N/2 + 1)机器后,异步复制其他slave。
该模式下下面的配置应该是一样的

"broker" ... >
  ...
  
    "activemq-data"
      replicas="3"
      bind="tcp://0.0.0.0:0"
      zkAddress="zoo1.example.org:2181,zoo2.example.org:2181,zoo3.example.org:2181"
      zkPassword="password"
      zkPath="/activemq/leveldb-stores"
      hostname="broker1.example.org"
      />
  
  ...
属性 默认值 注释
replicas 3 (replicas/2 + 1)数量避免集群宕机
securityToken 做复制时候的安全令牌
zkAddress 127.0.0.1:2181 使用逗号分隔一系列zk
zkPassword 连接到zk时候的密码
zkPath /default 主从切换时候选举信息
zkSessionTimeout 2s 检测一个zk节点是否宕机
sync quorum_mem 使用逗号分隔的一系列值,local_mem,local_disk,remote_mem,remote_disk,quonum_mem,quonum_disk,如果结合多种同样的话,disk优先取,quorum_mem等价于local_mem,remote_mem,quorum_disk等价于local_disk,remote_disk

每个节点都需要不同的

属性 默认值 注释
bind tcp://0.0.0.0:61619
hostname
weight 1 权重

标准的LevelDB存储属性

属性 默认值 注释
directory LevelDB 用于存储数据文件,不存在会自动创建
readThreads 10 read线程数量
logSize 104857600(100MB) 单个数据文件最大值
verifyChecksums false 校验数据文件
paranoidChecks false 存储error尽早抛出异常
indexFactory org.fusesource.leveldbjni.JniDBFactory, org.iq80.leveldb.impl.Iq80DBFactory LevelDB索引
indexMaxOpenFiles 1000 索引能使用openfile数量
indexBlockRestartInterval 16
indexWriteBufferSize 6291456(16MB) 写入到磁盘前内存索引数据大小
indexBlockSize 4096
indexCacheSize 268435456(256MB) 用于缓存索引快的内存
indexCompression snappy 用于索引块的压缩策略,snappy或者none
logCompression none 用于日志记录的压缩策略,snappy或者none
使用KahaDB作为存储

5.4版本以后activemq推荐使用kahaDB作为默认的存储机制
kahadb在activemq的使用

<broker brokerName="broker">
   <persistenceAdapter>
     <kahaDB directory="activemq-data" journalMaxFileLength="32mb"/>
   persistenceAdapter>
broker>

KahaDB 的属性

属性 默认值 注释
archiveCorruptedIndex false true为归档毁坏的索引(不删除)
archiveDataLogs false true表示把消息数据文件移动到归档目录(不删除)
checkForCorruptJournalFiles false true表示在启动的时候检查毁坏文件并尝试恢复
checkpointInterval 5000 单位毫秒
checksumJournalFiles true
cleanupInterval 30000 单位毫秒
compactAcksAfterNoGC 10 设置过大会影响性能,
compactAcksIgnoresStoreGrowth false
concurrentStoreAndDispatchQueues true
concurrentStoreAndDispatchTopics false 推荐设置为false
directory activemq-data 数据和日志文件目录
directoryArchive null 消费后消息归档位置
enableAckCompaction true
enableIndexWriteAsync false true表示异步更新索引
enableJournalDiskSyncs true 废,请看journalDiskSyncStrategy
ignoreMissingJournalfiles false true表示忽略遗失的日志文件
indexCacheSize 10000 在内存中缓存的索引页数量
indexDirectory 不设置使用directory目录
indexWriteBatchSize 1000 批量写入的索引数量
journalDiskSyncInterval 1000 单位毫秒,同步磁盘时间间隔
journalDiskSyncStrategy always always :periodic :never :
journalMaxFileLength 32mb
maxAsyncJobs 10000 队列存储最大的异步消息,应该与MessageProducer的数量一样
preallocationScope entire_journal_async 预分配文件
preallocationStrategy sparse_file 如何预先分配文件,sparse_file,设置文件长度,os_kernel_copy,委托给操作系统,zeros不设置文件长度
storeOpenWireVersion 11 5.9.0默认为6

networkConnector模式

网络模式
用于提供高可用,容灾的分布式队列和话题,客户端能够快速从宕机的broker切换到另外正常运作的broker。

networkConnector的配置
  1. 硬编码所有的networkConnector的元素(该模式也支持其他的传输协议,比如http)


<beans xmlns="http://activemq.org/config/1.0">

  <broker brokerName="receiver" persistent="false" useJmx="false">  
    <networkConnectors>
      <networkConnector uri="static:(tcp://localhost:62001)"/>
    networkConnectors>

    <persistenceAdapter>
      <memoryPersistenceAdapter/>
    persistenceAdapter>

   <transportConnectors>
      <transportConnector uri="tcp://localhost:62002"/>
    transportConnectors>
  broker>

beans>
  1. 使用自动发现检测broker(multicast or rendezvous)


<beans xmlns="http://activemq.org/config/1.0">

  <broker name="sender" persistent="false" useJmx="false">  
    <networkConnectors>
      <networkConnector uri="multicast://default"/>
    networkConnectors>

    <persistenceAdapter>
      <memoryPersistenceAdapter/>
    persistenceAdapter>

  <transportConnectors>
      <transportConnector uri="tcp://localhost:0" discoveryUri="multicast://default"/>
    transportConnectors>
  broker>

beans>

network Connector的配置形式如下

multicast://address:port?transportOptions
选项名称 默认值 描述
group default 起一个唯一名字避免多播阻塞
minmumWireFormatVersion 0 最小允许的wireFomat版本
trace false 记录传输的所有命令
useLocalHost true true表示本地机器命名为localhost
datagramSize 4 * 1024 UDP包的大小
timeToLive -1 数据包生存时间,设置大于1可以发送到其他的broker中
loopBackMode false 回路模式是否使用
wireFormat default 使用的WireFormat名字
wireFormat.* 用于配置wireFormat

使用默认值配置等价于multicast://239.255.2.3:6155

multicast://default 
multicast://224.1.2.3:6255?group=mygroupnam

OpenWire####

配置broker消息代理的信息
需要加上前缀wireFormat.

属性名 默认值 描述
cacheEnabled true
cacheSize 1024 当使用缓存时候,缓存的数量
maxInactivityDuration 30000 认为socket已经挂死的间隔时间然后主动杀死connection,为0表示不启用
maxInactivityDurationInitalDelay 10000 检查时延
maxFrameSize MAX_LONG 允许的帧大小,配置以避免oom
prefixPacketSize true
stackTraceEnabled ture
tcpNoDelayEnabled true
tightEncodingEnabled true
使用静态发现
<networkConnectors>
  <networkConnector uri="static:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
networkConnectors>

静态发现的属性

属性 默认值 描述
initialReconnectDelay initialReconnectDelay 单位毫秒,useExponentialBackOff为false情况下,第一次尝试重连的时间间隔
maxReconnectDelay 30000 单位毫秒,重连间隔时间
useExponentialBackOff true 每次重连失败都会增加重连时间间隔
backOffMultiplier 2 useExponentialBackOff每次增加时间
uri="static:(tcp://host1:61616,tcp://host2:61616)?maxReconnectDelay=5000&useExponentialBackOff=false"
MasterSlave discovery

建立网络桥接模式到一个broker以及她的slave中,使用masterslave来进行操作

<networkConnectors>
  <networkConnector uri="masterslave:(tcp://host1:61616,tcp://host2:61616,tcp://..)"/>
networkConnectors>

URI的顺序是
The URIs are listed in order for: MASTER,SLAVE1,SLAVE2…SLAVE(thumbs down)

NetworkConnector元素的属性
属性 默认值 描述
name bridge network的名称,两个相同broker之间的不同networkConnector使用不同的名字
dynamicOnly false true表示仅当进行持久订阅的时候network才激活,默认在启动时候就激活
decreaseNetworkConsumerPriority false true表示消费者启动时候优先级为-5,经过一个跳的network连接消费者就减少1,false表示所有的消费者使用与本地消费者同样的优先级0
networkTTL 1 消息和持久订阅能够穿越的broker数量 both message&consumer
messageTTL 1 消息能穿越的broker数量
consumerTTL 1 消费者能够穿越的broker数量
conduitSubscriptions true 多个消费者消费消息被当作一个消费者
excludedDestinations empty 在这个名单中的队列将不会在网络桥接模式在传递
dynamicallyIncludedDestinations empty 可以在网络桥接模式的broker传播,empty表示不在excludedDestinations中的队列都可以传播
useVirtualDestSubs false true表示监听虚拟队列的公告消息
staticallyIncludedDestinations empty 会在网络桥接中传播,即便没有消费者刚兴趣
duplex false 是否全双工作模式,true同时用于生产和消费消息
prefetchSize 1000 每次预取的数量
suppressDuplicateQueueSubscriptions false true表示网络桥接中两个broker复制消息将会被制止,比如,A,B,C三个broker使用multicast discovery,A上的消费者a会在产生B和C的broker上,此外,C上消费者也会连接到B,B消费者也会连接到C;为true的时候,BC之间的网络桥接将被禁止,因为她们已经订阅了Abroker上面的消息了,减少路由选择,用这种方法能够确定消除消息在死路由(卡住消息)网络中迁移的可能,networkTTL大于等于broker的数量时候需要这个属性进行调停。
bridgeTempDestinations true
alwaysSyncSend false true表示不持久化的消息使用请求应答的模式,这个配置对持久和非持久的选择都一样
staticBridge false true表示broker不会动态响应新的消费者,将会使用staticallyIncludedDestinations创建新的需求订阅。
userName null 远程broker的用户名
password null 密码

可靠性
如果源broker是持久订阅或者持久队列,network会保持持久化
如果源broker是非持久化的,发生异常会导致线上消息丢失

消息时序
无法保证消息时序,存在消费者从一个broker迁移到另外一个broker的情况。

管道订阅(Conduit subscription)
activemq使用活跃的消费者在network中传递消息。broker复制了一份远程broker的订阅,然后路由传送给本地的客户端连接。如果是话题或者是超过一个的订阅,多个副本将会消息产生。导管就是为了预防副本消息在整个network中泛滥传播,这个默认运行情况,使得多个订阅在远程的broker上行为就如同单个订阅一样。
然而,复制的订阅是一个有用的特性如果我们仅仅使用队列模式开发,这样子负载均衡算法就能把消息均匀的分配,如果conduitSubscriptions=false的话,在network上的消费者将会均分消息。比如AB两个broker,B上有2个消息者,A只有1个消费者,A生产了30个消息,在conduitSubscriptions=true的情况下,15个发送到A消费者,15个发送到B的borker上,如果conduitSubscriptions=false,10个发送到A,10个发送到B1,10个发送到B2。
Duplex network connectors
broker1配置到broker2的netwokrConnector是单向,如果设置duplex=true的话就是双向的了,
同时可以配置在同一个broker中配置多个networkConnector增加吞吐量

<networkConnectors>
        <networkConnector name="SYSTEM1" duplex="true" uri="static:(tcp://10.x.x.x:61616)">
                <dynamicallyIncludedDestinations>
                        <topic physicalName="outgoing.System1" />
                dynamicallyIncludedDestinations>
        networkConnector>
        <networkConnector name="SYSTEM2" duplex="true" uri="static:(tcp://10.x.x.x:61616)">
                <dynamicallyIncludedDestinations>
                        <topic physicalName="outgoing.System2"/>
                dynamicallyIncludedDestinations>
        networkConnector>
  networkConnectors>
Conduit subscriptions and consumer selectors

导管订阅忽略了在本地broker的消费者的selector并把消息传送给远程的消费者。远程的broker的selector在消息分发之前被解析,这在多broker中会存在问题。可以想象消息被A产生被传送到B或者C等broker,但是消息并不能满足B,C等broker等selector的特征,为了避免这种情况,要开启conduitSubscription这个属性。

networkConnector的配置陷阱

advisorySupport如果没有开启的话networkConnector可能会不正常的工作。
networkConnector严重依赖于advisory messages,消费者连接到远程的broker的话,会接收到所有关于advisory Message,在大规模情况下工作效果不会工作的很好。
只把特定队列的消息发送到远程broker。

<networkConnector uri="static:(tcp://host)">
  <dynamicallyIncludedDestinations>
    <queue physicalName="include.test.foo"/>
    <topic physicalName="include.test.bar"/>
  dynamicallyIncludedDestinations>
networkConnector>

在activemq的5.6版本或者更久远的需要增加前缀ActiveMQ.Advisory.Consumer.,配置demo如下

<networkConnector uri="static:(tcp://host)" destinationFilter="Queue.include.test.foo,ActiveMQ.Advisory.Consumer.Topic.include.test.bar">
  <dynamicallyIncludedDestinations>
    <queue physicalName="include.test.foo"/>
    <topic physicalName="include.test.bar"/>
  dynamicallyIncludedDestinations>
networkConnector>
Pure static networks

用于保存broker不受远程broker的消费者的影响,或者把当前broker当做一个用于传送消息的代理,可以考虑配置成static network

<networkConnector uri="static:(tcp://host)" staticBridge="true">
        <staticallyIncludedDestinations>
            <queue physicalName="always.include.queue"/>
        staticallyIncludedDestinations>
networkConnector>

staticBridge 参数在5.6版本以后使用,表示本地的broker不会从远程的broker订阅任何有关advisoryMessage,staticallyIncludedDestinations表示该队列或者是话题可以传播到远程的broker去,在5.6之前的版本不存在staticBridge的属性,我们可以destinationFilter 去监听没用到的advisory话题,类似下面的配置

<networkConnector uri="static:(tcp://host)" destinationFilter="NO_DESTINATION">
        <staticallyIncludedDestinations>
            <queue physicalName="always.include.queue"/>
        staticallyIncludedDestinations>
networkConnector>

如果像上述配置的话,broker将会尝试监听在ActiveMQ.Advisory.Consumer.NO_DESTINATION的新的消费者,并且不受远程broker的消费者影响。

Dynamic networks and Virtual Destinations

这里存在两个broker,LocalBroker配置的network如下

<networkConnector uri="static:(tcp://host)">
    <dynamicallyIncludedDestinations>
        <topic physicalName="include.bar"/>
    dynamicallyIncludedDestinations>
networkConnector>

remote Broker配置了组合话题如下

<compositeTopic name="include.bar" forwardOnly="false">
    <forwardTo>
        <queue physicalName="include.bar.forward" />
    forwardTo>
compositeTopic >

假设在remote Broker的include.bar.forward队列的存在一个消费者。往include.bar话题发送了一个消息的话,实际上将会被传送到
include.bar.forward队列并被消费掉。如果是往localBroker发布一个相同的话题,这个消息将不会传送到remoteBroker去。
消息之所以不会被传送是因为在include.bar.forward的消费者不能检测到localBroker的dynamicallyIncludedDestinations 列表,因为没有在原始队列(话题)include.bar的消费者,消息不会被传送到RemoteBroker。这里我们通过配置LocalBroker来监听虚拟目的地订阅来解决。

首先,当消费者的订阅符合虚拟目的地,我们需要配置remoteBroker发送advisoryMessage,在这个例子中,我们配置remoteBroker的useVirtualDestSubs 为true



<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true">  
     .....
  broker>

beans>

同时,配置localBroker监听advisoryMessage设置useVirtualDestSubs 为true

<networkConnector uri="static:(tcp://host)" useVirtualDestSubs="true">
  <dynamicallyIncludedDestinations>
    <topic physicalName="include.bar"/>
  dynamicallyIncludedDestinations>
networkConnector>

配置后在remoteBroker的队列include.bar.forward的消费者可以获取到从LocalBroker传送过来的include.bar的话题。

Virtual Destination Consumers on Destination Creation

让我们重新考虑上面的组合情况,如果没有消费者在remoteBroker的队列上,
remoteBroker的组合队列配置如下

<compositeTopic name="include.bar" forwardOnly="false">
    <forwardTo>
        <queue physicalName="include.bar.forward" />
    forwardTo>
compositeTopic >

组队话题配置在remoteBroker上,然后localBroker使用network连接到这个上面,即便我们开启了useVirtualDestSubs属性,消息也不会发送到没有消费者的remoteBroker上,这样子消息只会挤压在LocalBroker上,需要
设置remoteBroker的属性useVirtualDestSubsOnCreation=true,消息会发送到remoteBroker上,同时remoteBroker必须是
1到多个队列,拥有持久化的话题



<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true" useVirtualDestSubsOnCreation="true">  
     .....
  broker>

beans>
Composite Destination consumers and Virtual Topics

LocalBroker

<networkConnector uri="static:(tcp://host)">
  <dynamicallyIncludedDestinations>
    <topic physicalName="VirtualTopic.>"/>
  dynamicallyIncludedDestinations>
networkConnector>

RemoteBroker



<beans xmlns="http://activemq.org/config/1.0">

  <broker name="remoteBroker" useVirtualDestSubs="true" >  
     .....
  broker>

beans>
卡住的消息(Stuck Messages)

默认情况,消息是不允许回溯会他来自的broker,这样子就可以避免消息的传递成为一个环。偶然的情况下,存在需要消息重新回溯到原有队列。比如在这种情景,有两个broker,其中一个broker宕机后,消费者路由到另外一个broker中,然后宕机的broker被重启,但是没有消费者在宕机的broker上进行消费,所以宕机的broker重启后上挤压的消息没被消费掉,一个解决的方法是配置rebalanceClusterClients=true属性,另一种解决方法是允许消息回溯回他原来的broker。配置conditionalNetworkBridgeFilterFactory 标签的属性replayWhenNoConsumers=true。
如果是activemq版本小于5.9,需要关闭游标复制检测,enableAudit=false。conditionalNetworkBridgeFilterFactory 还可以调节消费速率限制。

<destinationPolicy>
  <policyMap>
    <policyEntries>
      <policyEntry queue="TEST.>" enableAudit="false">
        <networkBridgeFilterFactory>
          <conditionalNetworkBridgeFilterFactory replayWhenNoConsumers="true"/>
        networkBridgeFilterFactory>
      policyEntry>
    policyEntries>
  policyMap>
destinationPolicy>

你可能感兴趣的:(activemq)