mq在分布式系統中是所有系統的消息總線,在生產環境中必須要盡量保證mq的正常運行,所以一般都會使用master-slave,保證master掛掉時slave可以頂上繼續工作 . 但是僅僅是master-slave的話只能保證高可用,卻無法做到負載均衡,如果mq因負載過大掛掉, master-slave也無法解決這種問題,那么就必須配置負載均衡
activemq 的master-slave部署方式
- shared filesystem Master-Slave部署方式, 基于共享數據存儲目錄,多個broker共享存儲的文件系統,誰搶到存儲文件的控制權誰是master
- shared database Master-Slave方式 ,基于共享數據庫,跟第一種類似
- Replicated LevelDB Store方式,基于zookeeper + leveldb。 leveldb是谷歌的一個高性能kv數據庫. 這中方式是ActiveMQ5.9以后才新增的,原理就是使用ZooKeeper協調選舉一個node作為master, 被選擇的master broker node開啟并接受客戶端連接。如果master掛掉,得到了最新更新數據的slave就會成為master。掛掉的節點恢復后能夠重新加入到網絡中并連接master進入slave 模式.
前兩種要保證共享文件系統或數據庫的高可用和性能才能保證mq的高可用,有時候上述并不容易滿足,我們就使用第三種方式搭建master-slave集群.
環境
由于我們只有兩臺主機,我們測試就在每一臺主機上搭建一個偽master-slave集群,然后兩個集群再相互連接完成負載均衡
jdk : jdk8
zookeeper: 3.2
activemq: 5.15
主機1:192.168.0.103
主機2:192.168.0.104
搭建master-slave集群
步驟:
- 下載-->解壓-->拷貝3份activemq(5.9以后版本),保證單獨運行沒有問題
2.修改每個activemq的持久化方式
vi ACTIVEMQ_HOME/conf/activemq.xml
將默認的kahadb 修改為如下配置,zookeeper我做了集群,嫌麻煩直接使用單點Zookeeper也不影響
//directoryleveldb數據保存路徑
//bind 服務端口
//replicas表示master-slave集群中節點個數
//zkAddress依次指定三臺服務器的ip和ZooKeeper的監聽端口
//zkPah在zookeeper中注冊的節點路徑
//hostname為每一臺服務器的ip地址,三臺服務器根據實際情況修改
<persistenceAdapter>
<replicatedLevelDB directory="${activemq.data}/leveldb" replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="localhost:2181,localhost:2182,localhost:2183"
hostname="localhost"
zkPath="/activemq/leveldb-stores"/>
</persistenceAdapter>
3.修改activemq的TCP服務端口
該配置也在 ACTIVEMQ_HOME/conf/activemq.xml, 默認61616 , 相同機器不能重復,否則端口沖突,我這里為61616 ,61617, 61618
4.修改jetty端口
activemq 使用jetty運行服務, 修改 ACTIVEMQ_HOME/conf/jetty.xml 端口保證三個不能相同
依次改為8161 , 8162, 8163
- 啟動zookeeper, 啟動 三個activemq 實例
- 驗證
登錄Zookeeper 客戶端
執行: ls /activemq/leveldb-stores
查看節點發現/activemq/leveldb-stores下有三個節點,每一個代表一個activemq服務
image.png
查看每個節點的數據,其中elected 不為null 的就是master, 為null 的是slave
image.png
也可以下載zookeeper可視化工具:
https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip;
運行ZooInspector\build\zookeeper-dev-ZooInspector.jar 可以查看節點數據
ps:只有master接受請求,slave不接受請求,也無法使用管理界面
配置負載均衡
- 我們已經搭建好了一個集群, 可以使用scp 命令將三個activemq文件拷貝一份到另一臺主機即可得到另一個集群
#activemqCluster 是我本機的activemq 集群安裝目錄
scp -r activemqCluster root@192.168.0.103:/soft
- 在集群1的activemq.xml中鏈接集群2(在persistenceAdapter標簽前配置):
<networkConnectors>
<networkConnector uri="static:(tcp://192.168.0.103:61616,tcp://192.168.0.103:61617,tcp://192.168.0.103:61618)" duplex="false"/>
</networkConnectors>
- 在集群2的activemq.xml中鏈接集群1(在persistenceAdapter標簽前配置):
<networkConnectors>
<networkConnector uri="static:(tcp://192.168.0.104:61616,tcp://192.168.0.104:61617,tcp://192.168.0.104:61618)" duplex="false"/>
</networkConnectors>
這樣就實現了ActiveMQ的集群高可用負載均衡功能。
項目中activemq配置地址應改為:
failover:(tcp://192.168.0.103:61616,tcp://192.168.0.103:61617,tcp://192.168.0.103:61618)?randomize=false
或:
failover:(tcp://192.168.0.104:61616,tcp://192.168.0.104:61617,tcp://192.168.0.104:61618)?randomize=false
測試
1.測試master-slave , 關閉master(61616),自動切換master為61617并重新連接(切換時不能保證數據完整性). 再關閉一個服務61617,超過半數掛掉,服務不可用, 客戶端被阻塞不能再發送消息
-
測試負載均衡
最終的架構就是兩個master-slave集群 相互連通,兩個集群可以相互消費對方的消息,但是如果客戶端所連接的集群掛掉客戶端依然是不能發送消息的,也就是說activemq的負載均衡只是做到消費的負載均衡,高可用是靠master-slave來保證的。
我們啟動兩個消費者服務監聽相同的隊列名
mq的地址分別配置為
failover:(tcp://192.168.0.103:61616,tcp://192.168.0.103:61617,tcp://192.168.0.103:61618)?randomize=false
和:
failover:(tcp://192.168.0.104:61616,tcp://192.168.0.104:61617,tcp://192.168.0.104:61618)?randomize=false
啟動后向104集群不停發送消息,發現兩個消費者都能消費發送向104集群的消息,只不過打印日志有些區別,連接103集群的消費者服務顯示通過FailoverTransport連接到104的matser
至此,高可用+負載均衡搭建完畢.
最后說明一點,測試中發現在master-slave切換時消費的消息還是有可能會出現問題的,并不是萬無一失