ActiveMQ的多種部署方式
單點的ActiveMQ作爲企業應用無法滿足高可用和集羣的需求,所以ActiveMQ提供了master-slave、broker cluster等多種部署方式,但通過分析多種部署方式之後我認爲需要將兩種部署方式相結合才能滿足我們公司分佈式和高可用的需求,所以後面就重點將解如何將兩種部署方式相結合。
1)shared filesystem Master-Slave部署方式
主要是通過共享存儲目錄來實現master和slave的熱備,所有的ActiveMQ應用都在不斷地獲取共享目錄的控制權,哪個應用搶到了控制權,它就成爲master。
多個共享存儲目錄的應用,誰先啓動,誰就可以最早取得共享目錄的控制權成爲master,其他的應用就只能作爲slave。
2)shared database Master-Slave方式
與shared filesystem方式類似,只是共享的存儲介質由文件系統改成了數據庫而已。
這種主備方式是ActiveMQ5.9以後才新增的特性,使用ZooKeeper協調選擇一個node作爲master。被選擇的master broker node開啓並接受客戶端連接。
其他node轉入slave模式,連接master並同步他們的存儲狀態。slave不接受客戶端連接。所有的存儲操作都將被複制到連接至Master的slaves。
如果master死了,得到了最新更新的slave被允許成爲master。fialed node能夠重新加入到網絡中並連接master進入slave mode。所有需要同步的disk的消息操作都將等待存儲狀態被複制到其他法定節點的操作完成才能完成。所以,如果你配置了replicas=3,那麼法定大小是(3/2)+1=2. Master將會存儲並更新然後等待 (2-1)=1個slave存儲和更新完成,才彙報success。至於爲什麼是2-1,熟悉Zookeeper的應該知道,有一個node要作爲觀擦者存在。
單一個新的master被選中,你需要至少保障一個法定node在線以能夠找到擁有最新狀態的node。這個node將會成爲新的master。因此,推薦運行至少3個replica nodes,以防止一個node失敗了,服務中斷。
前面的Master-Slave的方式雖然能解決多服務熱備的高可用問題,但無法解決負載均衡和分佈式的問題。Broker-Cluster的部署方式就可以解決負載均衡的問題。
Broker-Cluster部署方式中,各個broker通過網絡互相連接,並共享queue。當broker-A上面指定的queue-A中接收到一個message處於pending狀態,而此時沒有consumer連接broker-A時。如果cluster中的broker-B上面由一個consumer在消費queue-A的消息,那麼broker-B會先通過內部網絡獲取到broker-A上面的message,並通知自己的consumer來消費。
在activemq.xml文件中靜態指定Broker需要建立橋連接的其他Broker:
1、 首先在Broker-A節點中添加networkConnector節點:
<networkConnectors>
<networkConnector uri="static:(tcp:// 0.0.0.0:61617)"duplex="false"/>
</networkConnectors>
2、 修改Broker-A節點中的服務提供端口爲61616:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
3、 在Broker-B節點中添加networkConnector節點:
<networkConnectors>
<networkConnector uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>
</networkConnectors>
4、 修改Broker-A節點中的服務提供端口爲61617:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
5、分別啓動Broker-A和Broker-B。
在activemq.xml文件中不直接指定Broker需要建立橋連接的其他Broker,由activemq在啓動後動態查找:
1、 首先在Broker-A節點中添加networkConnector節點:
<networkConnectors>
<networkConnectoruri="multicast://default"
dynamicOnly="true"
networkTTL="3"
prefetchSize="1"
decreaseNetworkConsumerPriority="true" />
</networkConnectors>
2、修改Broker-A節點中的服務提供端口爲61616:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61616? " discoveryUri="multicast://default"/>
</transportConnectors>
3、在Broker-B節點中添加networkConnector節點:
<networkConnectors>
<networkConnectoruri="multicast://default"
dynamicOnly="true"
networkTTL="3"
prefetchSize="1"
decreaseNetworkConsumerPriority="true" />
</networkConnectors>
4、修改Broker-B節點中的服務提供端口爲61617:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61617" discoveryUri="multicast://default"/>
</transportConnectors>
5、啓動Broker-A和Broker-B
2、Master-Slave與Broker-Cluster相結合的部署方式
可以看到Master-Slave的部署方式雖然解決了高可用的問題,但不支持負載均衡,Broker-Cluster解決了負載均衡,但當其中一個Broker突然宕掉的話,那麼存在於該Broker上處於Pending狀態的message將會丟失,無法達到高可用的目的。
由於目前ActiveMQ官網上並沒有一個明確的將兩種部署方式相結合的部署方案,所以我嘗試者把兩者結合起來部署:
這裏以Broker-A + Broker-B建立cluster,Broker-C作爲Broker-B的slave爲例:
1)首先在Broker-A節點中添加networkConnector節點:
<networkConnectors>
<networkConnector uri="masterslave:(tcp://0.0.0.0:61617,tcp:// 0.0.0.0:61618)" duplex="false"/>
</networkConnectors>
2)修改Broker-A節點中的服務提供端口爲61616:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
3)在Broker-B節點中添加networkConnector節點:
<networkConnectors>
<networkConnector uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>
</networkConnectors>
4)修改Broker-B節點中的服務提供端口爲61617:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
5)修改Broker-B節點中的持久化方式:
<persistenceAdapter>
<kahaDB directory="/localhost/kahadb"/>
</persistenceAdapter>
6)在Broker-C節點中添加networkConnector節點:
<networkConnectors>
<networkConnector uri="static:(tcp:// 0.0.0.0:61616)"duplex="false"/>
</networkConnectors>
7)修改Broker-C節點中的服務提供端口爲61618:
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61618?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
8)修改Broker-B節點中的持久化方式:
<persistenceAdapter>
<kahaDB directory="/localhost/kahadb"/>
</persistenceAdapter>
9)分別啓動broker-A、broker-B、broker-C,因爲是broker-B先啓動,所以“/localhost/kahadb”目錄被lock住,broker-C將一直處於掛起狀態,當人爲停掉broker-B之後,broker-C將獲取目錄“/localhost/kahadb”的控制權,重新與broker-A組成cluster提供服務。