ActiveMQ的高可用與負載均衡配置
1.1 高可用配置(Master/Slave)
當一個應用被部署於生產環境,災備計劃是非常重要的,以便從網絡故障,硬件故障,軟件故障或者電源故障中恢復。通過合理的配置ActiveMQ,可以解決上訴問題。最典型的配置方法是運行多個Broker,一旦某臺機器或者某個broker失效,其他broker能夠頂上去。這種方式叫做Master/Slave,一個broker作爲Master提供服務,而其他broker則作爲slave等待master失效從而頂上。客戶端需使用failover transport方式來連接broker。
目前activemq提供2種master/slave配置方式:
1) Sharing nothing:各broker擁有自己唯一的消息存儲
2) Sharing storage:各broker之間共享一個消息存儲設備,比如關係數據庫,共享文件系統等。但是一個時間段內只能有一個broker佔據他們。
1、 不共享式Master/Slave
該模式下,Master與Slave擁有各自獨立的消息存儲設備。他是最簡單的提供高可用性的消息Broker。Slave需要額外的配置,而Master不需要。所有的消息命令如消息、反饋、訂閱、事務等會被從master複製到slave,如圖所示,她發生在master收到這些消息之前。
slave啓動後會連接到master,所以master要先啓動起來。slave只有在master失效後纔會建立通信連接以頂替master。客戶端給master發送消息後,master會首先將他轉發到slave,等待slave反饋存儲完畢後,master纔開始處理這個消息。當master失效後,slave有2個選擇:
1) 關閉slave:管理員重新配置這個slave作爲master,然後再配置一個slave作爲替補,並將之前存儲的消息數據複製一份給slave,以同步。
2) 開啓通信端口並初始化網絡連接slave自動升級爲master
該模式的缺點:
1) master只會把slave連接後的消息傳給他,而連接master之前的消息,不會被複制過去。不過你可以通過配置waitForSlave屬性來讓master一直等待slave啓動纔開始工作。
2) master只允許一個slave,而slave不能再有slave
何時使用:
當master失效後,用戶可接受服務器維護時間,以及管理手工部署新的master和slave
2、 共享存儲式Master/Slave
不共享式的MasterSlave讓各個broker保持了相對獨立性,而共享式則是讓所有broker共享同一個存儲器,這個存儲器一定時間內只能被一個broker佔有。相比非共享式,優點是一旦master失效,無需手工恢復,而且也不限制slave
broker數量。
共享式目前分爲2種,共享數據庫和共享文件系統。值得一提的是,另外新的一種是基於zookeeper的,將會在5.9版中發佈。
1) 基於數據庫的共享:原理是把消息命令都存儲在數據庫中,並且在數據庫中加鎖,一旦master失效後,slave獲得該鎖後繼續服務。只要你擁有數據庫,並且不在意使用數據庫而造成的性能相對其他方式有所降低的話,可以考慮。
2) 基於共享文件系統的方式:其實就是把數據庫換成了一個共享文件系統如SAN等。
3) ReplicatedLevelDB Store(version 5.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失敗了,服務中斷。
PS:
l LevelDB是Google開源的持久化KV單機數據庫( NOSQL),具有很高的隨機寫,順序讀/寫性能,但是隨機讀的性能很一般,也就是說,LevelDB很適合應用在查詢較少,而寫很多的場景。
l 即便是使用zookeeper來進行master的選擇,客戶端在調用時,仍然要使用failover
:(tcp:
//broker1:61616,tcp://broker2:61616,tcp://broker3:61616)
的方式連接activemq服務器。
3、 使用方式(以共享文件系統爲例)
1) 部署Active MQ
將ActiveMQ的整個安裝文件(如apache-activemq-5.11.1-bin.zip)解壓多份(此處爲3份),分別放置在不同的IP的服務器上。
2) Active MQ配置
l 分別在上述三份ActiveMQ文件夾中的配置文件activemq.xml中進行持久化配置,如下例(這個位置必須爲一個網絡文件系統,如SAN,這樣不同的機器上的ActiveMQ才能訪問這個文件系統):
<persistenceAdapter>
<kahaDB directory=""/sharedFileSystem/sharedBrokerData"/>
</persistenceAdapter>
l 修改各自的IP及端口
<transportConnectors>
<transportConnectorname="openwire"uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
3) 客戶端配置示例(要使用failover並指定多個activemqURL)
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("failover
:(tcp:
//broker1:61616,tcp://broker2:61616,tcp://broker3:61616)
");
1.2 負載均衡(Network of Brokers)
Broker-Cluster部署方式中,各個broker通過網絡互相連接並共享queue。這在一定程度上可視爲負載均衡的一種方法。有兩種實現方式:靜態發現和動態發現。
1、 The StaticTransport(靜態發現,broker之間的協議,與client無關)
靜態發現協議使用硬編碼的形式,使得broker可以發現其他的broker,並共享queue。消息消費者可以從其中任意一個broker收到發給自己的消息。
示例如下:
[1]. 將ActiveMq拷貝2份,分別命名:
apache-activemq-5.10.0_M1,apache-activemq-5.10.0_M2,放在一臺機器上(測試而已)
[2]. M1做如下配置:
<!—配置靜態發現,使本broker可發現本機上61617端口的broker-->
<NetworkConnectors>
<networkConnector uri="static:(tcp://localhost:61617)"/>
</networkConnectors>
<transportConnectors>
<transportConnectorname="openwire" uri="tcp://0.0.0.0:61616?maximumConnectio ns=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
M2做如下配置:
<!—配置靜態發現,使本broker可發現本機上61616端口的broker-->
<networkConnectors>
<networkConnectoruri="static:(tcp://localhost:61616)"/>
</networkConnectors>
<transportConnectors>
<transportConnectorname="openwire" uri="tcp://0.0.0.0:61617?maximumConnectio ns=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
通過以上配置使M1和M2這兩個 broker通過網絡互相連接,並共享queue,
啓動M1和M2,可以看到如下啓動日誌:
可以看到M1和M2,networkconnection has been established
[3]. 測試代碼:
發送端鏈接tcp://localhost:61616,發送消息到queue,
接收端做如下修改:
connectionFactory = newActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,"tcp://localhost:61617");
經測試Receiver可以接受到數據,表示M1和M2已經共享了queue。
如果要實現故障轉移,則可將接收端的代碼改爲:
connectionFactory = newActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
" failover:(tcp://localhost:61617,tcp://localhost:61616)?randomize=false");
2、 The DiscoveryTransport(動態發現,broker之間的協議,與client無關)
DynamicDiscovery集羣方式在配置ActiveMQ實例時,不需要知道所有其它實例的URI地址對activemq.xml做如下配置:
[1]. M1做如下配置:tworkConnectors>
<networkConnectoruri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnectorname="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"
discoveryUri="multicast://default"/>
</transportConnectors>
[2]. M2做如下配置:
<networkConnectors>
<networkConnectoruri="multicast://default"/>
</networkConnectors>
<transportConnectors>
<transportConnectorname="openwire" uri="tcp://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"
discoveryUri="multicast://default"/>
</transportConnectors>
[3]. 啓動M1和M2,可以看到如下啓動日誌: network connection has beenestablished。
[4]. 測試代碼和結果同上。
1.3 高可用與負載均衡的綜合方案
暫無!!還沒搞清楚