個人部落格網:https://wushaopei.github.io/ (你想要這裡多有)
一、Activemq 的叢集思想
1、使用Activemq叢集的原因
面試題: 引入消息中間件後如何保證其高可用
2、叢集實作思路
基于zookeeper和LevelDB搭建ActiveMQ叢集。叢集僅提供主備方式的高可用叢集功能,避免單點故障。
3、叢集方案(共有三種)
主要是基于zookeeper+replicated-leveldb-store的主從叢集
- 基于shareFileSystem共享檔案系統(KahaDB)
- 基于JDBC
- 基于可複制的LevelDB
對比:
LevelDB,5.6版本之後推出了LecelDB的持久化引擎,它使用了自定義的索引代替常用的BTree索引,其持久化性能高于KahaDB,雖然預設的持久化方式還是KahaDB,但是LevelDB可能會是趨勢。
在5.9版本還提供了基于LevelDB和Zookeeper的資料複制方式,作為Master-Slave方式的首選資料複制方案。
二、zookeeper+replicated-leveldb-store的主從叢集
1、定義:
從ActiveMQ5.9開始,ActiveMQ的叢集實作方式取消了傳統的Masster-Slave方式.,增加了基于Zookeeper+LevelDB的Master-Slave實作方式,從5.9版本後也是官網的推薦。
基于Zookeeper和LevelDB搭建ActiveMQ叢集,叢集僅提供主備方式的高可用叢集功能,避免單點故障.
官網:http://activemq.apache.org/replicated-leveldb-store
2、官網叢集原理圖
位址:http://activemq.apache.org/replicated-leveldb-store
這幅圖的意思就是 當 Master 當機後,zookeper 監測到沒有心跳信号, 則認為 master 當機了,然後選舉機制會從剩下的 Slave 中選出一個作為 新的 Master 。
深入解析:
使用Zookeeper叢集注冊所有的ActiveMQ Broker但隻有其中一個Broker可以提供服務,它将被視為Master,其他的Broker處于待機狀态被視為Slave。
如果Master因故障而不能提供服務,Zookeeper會從Slave中選舉出一個Broker充當Master。Slave連接配接Master并同步他們的存儲狀态,Slave不接受用戶端連接配接。所有的存儲操作都将被複制到連接配接至Maste的Slaves。
如果Master當機得到了最新更新的Slave會變成Master。故障節點在恢複後會重新加入到叢集中并連接配接Master進入Slave模式。
所有需要同步的消息操作都将等待存儲狀态被複制到其他法定節點的操作完成才能完成。
是以,如給你配置了replicas=3,name法定大小是(3/2)+1 = 2。Master将會存儲更新然後等待(2-1)=1個Slave存儲和更新完成,才彙報success,至于為什麼是2-1,陽哥的zookeeper講解過自行複習。
有一個ode要作為觀察者存在。當一個新的Master被選中,你需要至少保障一個法定mode線上以能夠找到擁有最新狀态的ode,這個ode才可以成為新的Master。
是以,推薦運作至少3個replica nodes以防止一個node失敗後服務中斷。
3、部署規劃和步驟
- zookeper : 3.4.9 搭建zookeper 叢集,搭建 activemq 叢集
- 叢集搭建: 建立 /mq_cluster 将原始的解壓檔案複制三個,修改端口 (jetty.xml)
(1)環境和版本
(2)關閉防火牆并保證各個伺服器能夠ping通
(3)要求具備zk叢集并可以成功啟動
配置叢集教程:
1,建立我們自己的檔案夾存放Zookeeper
mkdir /my_zookeeper
2,下載下傳Zookeeper
wget -P /my_zookeeper/ https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.5.6/apache-zookeeper-3.5.6-bin.tar.gz
3,解壓
tar -zxvf apache-zookeeper-3.5.6-bin.tar.g
4,修改配置檔案
檔案名必須叫這個zoo.cfg
cp zoo_sample.cfg zoo.cfg
設定一下自定義的資料檔案夾(注意要手動建立這個目錄,後面會用到),,注意最後一定要有/結尾,沒有/會報錯這是坑
dataDir=/my_zookeeper/apache-zookeeper-3.5.6-bin/data/
在zoo.cfg件最後面追加叢集伺服器
server.1=192.168.10.130:2888:3888
server.2=192.168.10.132:2888:3888
server.3=192.168.10.133:2888:3888
(4)叢集部署規劃清單
(5)建立3台叢集目錄

就是一台電腦複制三份ActiveMQ
(6)修改管理控制台端口
說明: 就是ActiveMQ背景管理頁面的通路端口
(7)增加IP 到域名的映射(/etc/hosts 檔案)
說明:hostname名字映射(如果不映射隻需要吧mq配置檔案的hostname改成目前主機ip)
(8)ActiveMQ叢集配置
- 配置檔案裡面的BrokerName要全部一緻
2. 持久化配置(必須)
<persistenceAdapter>
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:62621"
zkAddress="192.168.10.130:2181,192.168.10.132:2181,192.168.10.133:2181"
hostname="192.168.10.130"
zkPath="/activemq/leveldb-stores"
/>
</persistenceAdapter>
(9)修改各個節點的消息端口
02 節點 =》 61617 03 節點 =》 61618
(10)按順序啟動3個ActiveMQ節點,到這步前提是zk叢集已經成功啟動運作
- 先啟動Zk 在啟動ActiveMQ
- vim amq_batch.sh
- 想要啟動replica leavel DB 必須先啟動所有的zookeper 服務,zookeper 的單機僞節點安裝這裡不細說了,主要說zookeper 複制三份後改配置檔案,并讓之自動生成 myid 檔案,并将zk的端口改為之前表格中對應的端口 。這是conf 下的配置檔案
- 其具體配置為:
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2191 // 自行設定
server.1=192.168.17.3:2888:3888
server.2=192.168.17.3:2887:3887
server.3=192.168.17.3:286:3886
dataDir=/zk_server/data/log1 // 自行設定
- 建立批量啟動腳本
#!/bin/sh // 注意這個必須寫在第一行
cd /zk_server/zk_01/bin
./zkServer.sh start
cd /zk_server/zk_02/bin
./zkServer.sh start
cd /zk_server/zk_03/bin
./zkServer.sh start
編寫這個 zk_batch.sh 之後, 使用
chmod 700 zk_batch.sh
指令即可讓它變為可執行腳本, ./zk_batch.sh start 即可 (即啟動了三個zk 的服務)
同理可以寫一個批處理關閉zk 服務的腳本和 批處理開啟mq 服務 關閉 mq 服務的腳本。
完成上述之後連接配接zk 的一個用戶端
./zkCli.sh -server 127.0.0.1:2191
(11) zk叢集節點狀态說明
連接配接之後:
表示連接配接成功!
檢視我的三個節點: 我的分别是 0…… 3 …… 4 …… 5
檢視我的節點狀态
get /activemq/leveldb-stores/00000000003
此次驗證表明 00000003 的節點狀态是master (即為63631 的那個mq 服務) 而其餘的(00000004 00000005) activemq 的節點是 slave
如此叢集順利搭建成功 !
此次測試表明隻有 8161 的端口可以使用 經測試隻有 61 可以使用,也就是61 代表的就是master
三、測試叢集可用性
1、叢集可用性
ActiveMQ的用戶端隻能通路Master的Broker,其他處于Slave的Broker不能通路,是以用戶端連接配接的Broker應該使用failover協定(失敗轉移)
當一個ActiveMQ節點挂掉或者一個Zookeeper節點挂點,ActiveMQ服務依然正常運轉,如果僅剩一個ActiveMQ節點,由于不能選舉Master,是以ActiveMQ不能正常運作。
同樣的,
如果zookeeper僅剩一個活動節點,不管ActiveMQ各節點存活,ActiveMQ也不能正常提供服務。
(ActiveMQ叢集的高可用依賴于Zookeeper叢集的高可用)
2、修改代碼并測試:
public static final String ACTIVEMQ_URL = "failover:(tcp://192.168.17.3:61616,tcp://192.168.17.3:61617,
tcp://192.168.17.3:61618)?randomize=false";
public static final String QUEUE_NAME = "queue_cluster";
測試:
測試通過連接配接上叢集的 61616
MQ服務收到三條消息:
消息接收
MQ 服務也将消息出隊
以上代表叢集可以正常使用
3、真正的可用性測試:
殺死 8061 端口的程序 !!!
重新整理頁面後 8161 端口宕掉,但是 8162 端口又激活了
當 61616 當機,代碼不變繼續發消息 自動連接配接到 61617 了
這樣! 叢集的可用性測試成功!