ActiveMQ叢集配置及使用
為什麼要對訊息中介軟體叢集?
實現高可用,以排除單點故障引起的服務中斷
實現負載均衡,以提升效率為更多使用者提供服務
叢集方式:
客戶端叢集:讓多個消費者消費同一個佇列
Broker clusters:多個Broker之間同步訊息
Master Slave:實現高可用
客戶端配置:
ActiveMQ失效轉移(falilover):
允許當其中一臺訊息伺服器宕機時,客戶端在傳輸層上重新連線到其他訊息伺服器。
語法:failover:(uri1,....,uriN)?transportOptions
transportOptions引數說明:
randomize:預設為true,表示在URI列表中選擇URI連線時是否採用隨機策略
initialReconnectDelay:預設10毫秒,表示第一次嘗試重連之間等待的時間
maxReconnectDelay:預設30000毫秒,表示最長重連的時間間隔
Broker clusters叢集配置:
原理:兩個節點,節點A和節點B,節點A可以把訊息同步到節點B,節點B可以把訊息同步到節點A,同步之後,節點A接收到的訊息可以被節點B的消費者消費,反之亦然,其實現方式是通過"網路聯結器"來實現的。
網路聯結器:網路聯結器主要用於配置ActiveMQ伺服器與伺服器之間的網路通訊方式,用於伺服器透傳訊息。又分為靜態聯結器和動態聯結器。
靜態聯結器配置:
<networkConnectors>
<networkConnector uri="static:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)"/>
</networkConnectors>
動態聯結器配置:
<networkConnectors>
<networkConnector uri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnector uri="tcp://localhost:0" discoveryUri="multicast://default
</transportConnectors>
Master Slave叢集配置:
ActiveMQ Master Slave叢集方案:
1.Shared storage master/slave 共享儲存
2.Replicated LevelDB Store 基於複製的LevelDB Store
共享儲存叢集的原理:
比如有兩臺伺服器節點A和節點B,他們有一個共享的持久化地址,先啟動節點A,A獲得排它鎖獨佔資源成為Master,B成為Slave,若A掛掉,B將獲得持久化資源的排它鎖成為Master接收客戶端的請求,客戶端通過失效轉移將請求傳送到了B,完成了請求的不間斷性,達到高可用效果。
基於複製的LevelDB Store的原理:
因為LevelDB是基於ZK的,所以它的伺服器至少有三個,每個節點都有自己的儲存化方式,他們共有一個zk節點,通過zk來選取一臺伺服器作為Master,A就具有了提供給外部服務的能力,獲得外部訊息資源後在本地"store"儲存,再通過zk將訊息同步給B和C儲存起來,若A故障,zk會選取另一臺伺服器成為Master。
兩種叢集方式的對比
Master/Slave實現了高可用,因為一臺伺服器掛掉,另一臺伺服器可以馬上頂替上去,且保證了訊息不會丟失,但是無法做到負載均衡,因為Slave伺服器不能提供服務。
Broker Cluster不能實現高可用,因為它獲得的訊息沒有做持久化,若某個伺服器掛掉,它正在處理的訊息就會丟失,但是做到了負載均衡,因為A節點的訊息可以被節點B的消費者消費,B節點的訊息可以被節點A的消費者消費。
如何做到兩者兼備呢?
下面是網上找的一種三臺伺服器的完美叢集方案:無論A,B,C哪個伺服器宕機,都不會影響服務的正常執行,保證了高可用,又因為B、C和A之間的訊息同步,實現了B、A或C、A之間可以互相消費彼此的訊息,實現了負載均衡。
ActiveMQ三臺伺服器的完美叢集具體配置方案:
因為只有一臺電腦,所以只能通過開放不同埠的方法來實現一臺電腦部署三個伺服器
先新建三個actvemq服務目錄activemq-A,activemq-B,activemq-C,一個持久化目錄share-DB
將apache-activemq-5.14.2複製進A,B,C三個目錄中
進入activemq-A的apache-activemq-5.14.2的conf,編輯activemq.xml
將除了埠61616的配置註釋掉
新增網路聯結器配置,將B,C的uri新增進來:
還需要編輯conf目錄下的jetty.xml(提供後端管理地址的jetty伺服器)
因為A節點使用的就是預設的8161埠,因此不用修改
以下是B節點activemq.xml的配置:
這是持久化目錄的配置
<persistenceAdapter>
<kahaDB directory="/opt/app/actvemq/share-DB"/>
</persistenceAdapter>
網路聯結器的配置:
<transportConnector name="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<!--<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>-->
</transportConnectors>
<networkConnectors>
<networkConnector name="network_A" uri="static:(tcp://127.0.0.1:61616)"/>
</networkConnectors>
jetty服務埠則改為8162
C節點配置就不一一展示了,模仿B節點修改就行。
最後依次啟動A,B,C節點,檢視相應埠,可以看出因為先啟動activemq-B所以它成為Master,C節點成為Slave不提供服務(程序狀態TiIME_WAIT)
用我的部落格"簡單使用ActiveMQ"裡的程式碼進行測試,不過還要進行客戶端失效轉移的配置,很簡單就修改兩處地方:
AppPoducer.java:
private static final String url="failover:(tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)?randomize=true";
AppConsumer.java:
private static final String url="failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)?randomize=true";