目錄
1.概要
2.ActiveMQ基于 ZooKeeper + levelDB 的 HA 叢集搭建
3.ActiveMQ 叢集高可用案例
1.概要
使用 ZooKeeper 實作的 master-slave 實作方式,是對 ActiveMQ 進行高可用的一種有效的解決方案。即:每一個 節點的 Broker 在 ActiveMQ 啟動完成後,會将該節點相關資訊注冊至 Zookeeper,通過 ZooKeeper 的節點動态感覺特性,來實作主從切換、選舉等問題。
在 ZooKeeper + ActiveMQ 叢集中,隻有其中的一個 Broker 可以對外提供服務(也就是 master 節點),其他的 Broker 節點都處于待機狀态(也就是 slave 節點)。如果 master 節點因故障問題而不能對外一共服務時,則利用 ZooKeeper 的内部選舉機制,會從 Slave 中選舉出一個 Broker 來充當 master 節點,繼續的對外提供服務。
2.ActiveMQ基于 ZooKeeper + levelDB 的 HA 叢集搭建
ActiveMQ5.9 以後,推出了基于 ZooKeeper 的 master/slave 主從實作叢集。雖然 ActiveMQ 不建議使用 LevelDB 作為存儲,主要原因是社群的主要精力都集中在 kahaDB 的維護上,包括 bug 修複等。是以并沒有對 LevelDB 做太多的關注,是以它暫時是不作為推薦商用。但實際上在很多公司,仍然采用了 ZooKeeper + LevelDB 方式的高可用叢集方案。而實際推薦的方案,仍然是基于KahaDB的檔案共享(請移步:ActiveMQ 靜态網絡連接配接配置) 以及 JDBC的方式來實作(資料庫讀寫,效率低)。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓如下是 ActiveMQ 基于 ZooKeeper + levelDB 的 HA 高可用叢集的搭建↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
ActiveMQ 基于 LevelDB 叢集搭建官方文檔(英文版):ZooKeeper + LevelDB 叢集搭建
2.0 叢集方案
ZooKeeper叢集
主機IP | 消息端口 | 通信端口 |
192.168.204.201 | 2181 | 2888:3888 |
192.168.204.202 | 2181 | 2888:3888 |
192.168.204.203 | 2181 | 2888:3888 |
ActiveMQ叢集
主機IP | 叢集通信端口 | Web控制台端口 | 連接配接Broker節點端口 |
192.168.204.201 | 61619 | 8161 | 61616 |
192.168.204.202 | 61620 | 8161 | 61616 |
192.168.204.203 | 61621 | 8161 | 61616 |
2.1 ZooKeeper叢集搭建
基于 ZooKeeper 來搭建 ActiveMQ 叢集,前提是需要有一個 ZooKeeper 來進行管理,為了保證 ZooKeeper 的高可用,建議搭建至少3個節點的ZooKeeper叢集。如需了解 ZooKeeper 叢集的安裝,請移步:ZooKeeper叢集的安裝 (如需了解更多關于ZooKeeper 知識,請移步:ZooKeeper 總結)
2.2 ActiveMQ叢集搭建
1.進入ActiveMQ官網,點選下載下傳:ActiveMQ所有曆史版本
2.本文下載下傳的是最新版本:ActiveMQ-5.15.9
3.通過 tar zxvf 檔案名,将tar.gz包解壓縮至指定路徑。本文路徑:/usr/local/lib/activemq-cluster
4.進入 activemq-cluster 目錄,通過 mv 指令 重命名 為 activemq
5.接下來,便是配置檔案的修改。進入 activemq/conf 目錄下,分别對叢集每個節點 activemq.xml 檔案進行配置,配置如下:
①在 <persistenceAdapter> 注釋掉預設 kahadb 方式存儲
②添加基于 LevelDB 方式的叢集配置,具體配置如下:
<persistenceAdapter>
<!-- 1.注釋掉kahaDB方式存儲 -->
<!-- <kahaDB directory="${activemq.data}/kahadb"/>-->
<!-- 2.配置基于LevelDB方式存儲 + 叢集配置 -->
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
<!-- 不同節點,該端口需修改.192.168.204.202節點,此處端口修改為61620,一次類推,每個節點bind内容必須唯一 -->
bind="tcp://0.0.0.0:61619"
zkAddress="192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181"
zkPath="/activemq/leveldb-stores"
<!-- 不同節點,該IP需修改.192.168.204.202節點,此處IP修改為192.168.204.202一次類推,每個節點bind内容必須唯一 -->
hostname="192.168.204.201"
/>
</persistenceAdapter>
6.配置參數介紹:
屬性名 | 配置介紹 | 叢集每個節點該屬性是否必須唯一 |
directory | 表示 LevelDB 所在的主工作目錄(類似kahaDB) | 否 |
replicas | 表示叢集總的節點數,用于 master 選舉使用。比如我們的叢集有 3 個節點,且最多允許一個節點出現故障,那麼這個值可以設定為 2,也可以設定為 3 。因為計算公式為(replicas/2)+ 1。如果我們設定為4,就表示不允許 3 個節點的任何一個節點出錯。建議選擇奇數節點; | 否 |
bind | 表示當【目前】的節點為 master 時,它會根據綁定好的位址和端口來進行主從複制協定。還支援使用動态端口,隻需要使用 tcp://0.0.0.0:0 進行配置;(每個節點端口不能一樣) | 是(不同節點需要修改端口号) |
zkAddress | ZooKeeper的位址。叢集模式通過逗号分隔 | 否 |
zkPath | ActiveMQ 啟動時,向 ZooKeeper 中注冊的節點路徑 | 否 |
hostname | 本機IP。用于在此節點成為主節點時通告複制服務的主機名。 如果未設定,将自動确定。 | 是(不同節點需要修改為本機IP) |
7.叢集之間通信,切記開放指定端口号;亦可關閉防火牆。【生産環境情況下,建議開放端口,不建議關閉防火牆】
本文叢集之間通信,用到 61619 、 61620 、 61621 三個端口,開放這三個端口即可。在 Linux 中如何開放指定端口号,請移步:Linux開放指定端口,如下圖所示。8161 和 61616 端口也記得打開,分别是 Web 控制台端口和用戶端連接配接 Broker 端口。
8.至此,ActiveMQ 基于 ZooKeeper + LevelDB 的 HA 叢集就搭建完成了
9.啟動叢集之前,先啟動 ZooKeeper 叢集,然後再啟動 ActiveMQ 叢集。
如何啟動ZooKeeper叢集,請移步:ZooKeeper叢集的安裝
啟動ActiveMQ叢集,分别進入每個節點activemq/bin目錄下,通過指令: sh activemq start 啟動
10.啟動完成不報錯,則說明 ActiveMQ 叢集配置成功
日志路徑:activemq/data/activemq.log 。通過 tail 指令檢視即可。如果有錯誤,可以參考 單機版 ActiveMQ 安裝 來解決,如有其他問題沒有提到,請自行 Baidu or Google。啟動成功圖示如下:(請輕按兩下放大,通過Ctrl+滑鼠滾輪 縮放檢視,因為我是雙顯示器,哈哈)
出現如下提示:jolokia-agent: Using policy access restrictor classpath:/jolokia-access.xml | /api | main,則說明目前該節點是 master節點。目前 master 節點 IP 是 192.168.204.201。
11.此時,你可以通過 http://masterIP:8161 進入web控制台頁面檢視。其他的 Broker 節點由于都是處于待機狀态,是以你是無法進入到 web控制台頁面的。隻能進入目前 master 的頁面。即:ActiveMQ叢集正常運作,你隻能進入 master 節點的 web控制台頁面。
3.ActiveMQ 叢集高可用案例
ActiveMQ 高可用,此處會用到一個 failover 故障轉移機制,隻需要在 brokerURL中通過如下配置即可:
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
"failover:(tcp://192.168.204.201:61616,tcp://192.168.204.202:61616,tcp://192.168.204.203:61616)"
);
Producer端:(消息生産端)
public class Producer {
public static void main(String[] args) throws InterruptedException {
//1.建立連接配接工廠
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(tcp://192.168.204.201:61616,tcp://192.168.204.202:61616,tcp://192.168.204.203:61616)");
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
//2.擷取連接配接
connection = connectionFactory.createConnection();
//3.啟動連接配接
connection.start();
//4.建立會話
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//5.建立隊列對象(目的地)
Destination destination = session.createQueue("myQueue");
//6.建立消息生産者
producer = session.createProducer(destination);
for (int i = 0; i < 1000 ; i++) {
//7.建立消息
TextMessage message = session.createTextMessage("ActiveMQ:"+i);
//8.發送消息
producer.send(message);
}
} catch (JMSException e) {
e.printStackTrace();
} finally {
try {
if(producer != null){
producer.close();
}
if(connection != null){
connection.close();
}
if(session != null) {
session.close();
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
Consumer端:(消息消費端)
public class Consumer01 {
public static void main(String[] args) {
//1.建立連接配接工廠
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(tcp://192.168.204.201:61616,tcp://192.168.204.202:61616,tcp://192.168.204.203:61616)");
Connection connection = null;
Session session = null;
try {
//2.擷取連接配接
connection = connectionFactory.createConnection();
//3.啟動連接配接
connection.start();
//4.建立會話
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//5.建立隊列對象(目的地)
Destination destination = session.createQueue("myQueue");
//6.建立消息消費者
MessageConsumer consumer = session.createConsumer(destination);
for (int i = 0; i < 10; i++) {
//7建立消息 & 消費消息
TextMessage message = (TextMessage)consumer.receive();
System.out.println(message.getText());
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(connection != null){
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
if(session != null){
try {
session.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
}
案例測試:
①啟動 Producer 端,生産1000條消息。然後在 Consumer 端開始消費。目前連接配接 master 節點為 192.168.204.201 節點,開始生産1000條消息
②在 Consumer 端消費,消費1條休眠1000ms,當消費到幾條資料後,我們手工關閉 192.168.204.201 的 master 節點,叢集則會通過 ZooKeeper選舉機制開始新 master 的選舉。然後你會看到 Consumer 端,會通過故障轉移機制,重新連接配接至新的 master 節點,繼續消費消息。如下圖所示:
Consumer 端開啟消費,連接配接至 master 192.168.204.201 節點,當消費至 ActiveMQ:6 後,通過2圖 kill 指令強制關閉 201 master節點,你會看到 2 圖 開始重新選舉,然後 192.168.204.202 節點提示:jolokia-agent: Using policy access restrictor classpath:/jolokia-access.xml | /api | main,則說明192.168.204.202 節點被選舉為 master節點。然後你再檢視 1 圖,你發現在報錯後,通過故障轉移,消費端連接配接至 192.168.204.202 這個新選舉的 master 繼續消費。這樣便完成了 ActiveMQ + LevelDB的 HA 高可用叢集的使用。(2圖請輕按兩下放大檢視)
當 192.168.204.201 節點重新啟動後,會變成 192.168.204.202 的 slave 節點。
ActiveMQ 基于 ZooKeeper + LevelDB的高可用叢集,配置 + 使用,到此結束。寫部落格好累的說,喜歡的給個贊吧 ^_^
END