1、ActiveMQ的高可用性
ActiveMQ使用master-slave模式實現高可用性,提供兩種實現主從模式的配置:shared nothing、shared storage(a relational database and a shared file system)java
1.shared nothing master-slave數據庫
每個broker(包括master和slave)都有本身的消息存儲區,這是最簡單的高可用性實現的辦法。
master複製全部的消息指令給slave,複製的動做發生在master回覆client消息已接收以前。
slave broker會在啓動的時候去鏈接master,因此理想上,master broker應該先啓動,slave broker 不會打開任何transports,也就是說,slave broker不接收任何client請求和網絡鏈接,除非master掛掉。slave經過檢測它與master之間的鏈接失敗而斷定master掛掉。apache
shared nothing master-slave模式的處理過程:當一個生產者發送一個持久化消息到master以後,master會複製該消息給slave,再返回接收應答給生產者,生產者才能發送下一個消息。bash
當master broker掛掉後,slave有兩個選擇:
1.關掉本身,所以,它只會保存master的狀態。
2.打開transports而且初始化全部的network connections,所以,該slave自動成爲新的master。網絡
若是slave broker成爲新的master broker,全部的client能夠經過failover機制去鏈接上新的master。在默認的client鏈接中,failover傳輸機制皆能夠鏈接到master和slave:
failover://(tcp://masterhost:61616,tcp://slavehost:61616)?randomize=false架構
不過,使用shared nothing master-slave也有限制,若是client先連上master進行工做,而slave還沒與master進行鏈接,master掛掉,消息極可能會丟失。ActiveMQ提供了一個waitForSlave屬性去設置master broker,強制master若是還沒與slave創建好鏈接,那麼不會接受任何client的鏈接,另外一個限制是,一個master只容許有一個slave。併發
配置shared nothing master-slave
配置一個broker成爲slave很簡單,配置一個masterConnector service:dom
<services>
<!--
remoteURI:master broker的監聽地址
userName:Optional,若是master須要身份驗證
password:Optional,若是master須要身份驗證
-->
<masterConnector remoteURI="tcp://remotehost:62001" userName="" password=""/></services>複製代碼
2.shared storage master-slave
share nothing master-slave模式下,每個broker都獨自維護本身的storage,而shared storage master-slave模式容許多個broker共享存儲,但同一個時刻只有一個broker是存活的。shared storage master-slave的好處在於,它確保了當master掛掉以後,無需手動干預去保持應用的完整性,另外一個好處是,slave的數量再也不有所限制。
share nothing master-slave模式的配置有兩種:a relational database和file system-based storage.tcp
shared database master-slave分佈式
當一個ActiveMQ broker使用關係型數據庫時,它持有表的鎖以確保沒有其餘broker同時訪問這個數據庫。多個broker同時運行並嘗試去訪問數據庫時,只有第一個broker會鏈接成功並拿到鎖,其餘隨後到來的broker會一直poll直到它能夠得到鎖爲止。這些處於polling狀態的broker,被視爲slave,它們不會開啓任何傳輸鏈接或者網絡鏈接。
該配置中全部的broker可使用同一份配置文件,這使得activemq啓動起來簡單得多。
shared file system master-slave
它建議使用 KahaDB 消息存儲,可是對於消息存儲使用底層的共享的文件系統。當KahaDB消息存儲啓動時,它將嘗試獲取文件鎖,以防止任何其餘broker同時訪問基於文件的消息存儲。
2、ActiveMQ是如何在brokers之間傳遞消息
ActiveMQ中有一個概念:networks of brokers,它指的是鏈接ActiveMQ的消息代理在一塊兒造成不一樣的拓撲結構。
接下來就是分析brokers是如何在一個network中發現彼此且如何配置broker使其在network中合做。
1.存儲和轉發(store and forward)
ActiveMQ的存儲和轉發概念意味着,消息在經過network轉發到其餘broker以前,老是被存儲在本地broker中,也就是說,若是一條消息因爲鏈接緣由沒有被交付,好比說,正在重連,broker將可以經過網絡鏈接將未交付的消息發送到遠程broker。默認狀況下,network僅以單向方式操做,如圖:
固然,這並非說network只能單向操做,若是想要雙向操做,一樣能夠在遠程broker中配置一個network connector指向本地的broker,或者直接指定建立的network connector爲雙向duplex。
當本地broker和遠程broker之間創建好一條network後,遠程broker會將其全部持久和處於活動的消費者的目的地信息傳遞給本地broker,本地broker使用這些信息去判斷遠程broker對哪一種消息感興趣,並轉發該類型消息給它。
這裏,書中舉了一個場景,假如咱們有多個超市須要鏈接到一個後臺辦公訂購系統,這將很難靈活擴展新的超市,後臺辦公訂購系統很差掌控全部新加入的超市即遠程broker。
給個圖示,這裏想象超市和後臺之間有一個防火牆。(至於爲何這麼想象,我並不得知)注意到這裏,超市broker和back office之間的network是雙向的,超市broker的配置:
<networkConnectors>
<networkConnector uri="static://(tcp://backoffice:61617)"
name="bridge"
duplex="true"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false">
</networkConnector></networkConnectors>複製代碼
這裏關於配置,主要注意一點是,配置的順序是很重要的,關於networks,persistence,transports的順序以下:
Networks——必須在消息存儲以前建立
Message store——必須在傳輸配置好以前配置完
Transports——必須在broker配置的最後
舉個例子:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://activemq.apache.org/schema/core">
<broker brokerName="receiver" persistent="true" useJmx="true">
<networkConnectors>
<networkConnector uri="static:(tcp://backoffice:61617)"/>
</networkConnectors>
<persistenceAdapter>
<kahaDB directory = "activemq-data"/>
</persistenceAdapter>
<transportConnectors>
<transportConnector uri="tcp://localhost:62002"/>
</transportConnectors>
</broker></beans>複製代碼
來一張,在大型開發場景下的高可用性和network配置結合:
2.Network發現機制
ActiveMQ提供兩種發現機制:
Dynamic——使用組播和會合方式搜索brokers
Static——經過一個URI列表配置brokers
使用組播發現的方式去建立network鏈接是最簡單粗暴的,當你啓動一個broker時,它會經過組播IP去搜索其餘的broker並建立network鏈接。配置方式以下:
<networkConnectors> <networkConnector uri="multicast://default"/></networkConnectors>複製代碼
這裏「default」表示這個broker屬於哪一個組,建議使用惟一的名字去標識,以避免你的broker鏈接到其餘你不知道的應用代理上。
組播發現機制有一些限制,好比說不能控制哪些broker被發現,事實上,它一般侷限於本地網段上去發現其餘broker,由於組播IP不經過路由器延伸。
關於第二種方式,static,事實上,在這以前的配置一直都是static,只不過broker的URL列表有點少而已,
<networkConnectors> <networkConnector uri="static:(tcp://remote-master:61617,tcp://remote-slave:61617)"/></networkConnectors>複製代碼
static的配置屬性:
3.Network配置
對於遠程broker現存在的目的地,可能沒有任何活動持久的訂閱者或消費者,所以,當network初始化鏈接到遠程broker時,遠程broker會讀取它現存目的地的消息,並傳遞給本地broker,而後,本地broker也能夠轉發那些目的地的消息。
重要的是要注意,一個network將使用broker的名稱來表明遠程broker建立惟一的持久預訂代理。 所以,若是在稍後的時間點更改broker的名稱,極可能會經過network丟失持久主題訂閱者的消息。 爲避免這種狀況,請確保爲元素上的brokerName屬性使用惟一的名稱。 有關簡要示例,請參閱如下內容:
<broker xmlns="http://activemq.apache.org/schema/core/"
brokerName="brokerA"
dataDirectory="${activemq.base}/data">... <networkConnectors>
<networkConnector name="brokerA to brokerB" uri="tcp://remotehost:61616"/>
</networkConnectors></broker>複製代碼
關於Network配置還有不少,不一一列舉了。
3、爲大量併發應用程序部署ActiveMQ
擴展使用ActiveMQ的應用程序可能須要一些時間,須要一些努力。 在本節中,將介紹三種技術來幫助完成此任務。首先是垂直擴展,單個broker用於數千個鏈接和隊列。而後將經過使用network水平擴展應用程序來擴展到數萬個鏈接。 最後,將研究流量分區,這將平衡擴展和性能,但會增長ActiveMQ應用程序的複雜性。
1.垂直擴展
垂直擴展是一種用於增長單個ActiveMQ broker能夠處理的鏈接數(所以增長負載)的技術。默認狀況下,ActiveMQ broker設計爲儘量高效地移動消息,以確保低延遲和良好的性能。可是咱們能夠作一些配置調整,以確保ActiveMQ broker能夠處理大量的併發鏈接和大量的隊列。
默認狀況下,ActiveMQ將使用阻塞I/O來處理傳輸鏈接。 這致使每一個鏈接使用一個線程。 咱們能夠在ActiveMQ broker上使用非阻塞I/O(而客戶端上仍然使用默認傳輸)來減小使用的線程數。broker的非阻塞I/O配置以下:
<broker> <transportConnectors>
<transportConnector name="nio" uri="nio://localhost:61616"/>
</transportConnectors></broker>複製代碼
除了每一個鏈接使用一個線程來阻塞I/O外,ActiveMQ broker可使用線程爲每一個客戶端鏈接分派消息。能夠經過將名爲org.apache.activemq.UseDedicatedTaskRunner的系統屬性設置爲false,讓ActiveMQ使用線程池。
ACTIVEMQ_OPTS="-Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
確保ActiveMQ broker具備足夠的內存來處理大量併發鏈接有兩步過程。
首先,須要確保啓動ActiveMQ broker的JVM配置了足夠的內存。
ACTIVEMQ_OPTS="-Xmx1024M -Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
第二,確保專門爲ActiveMQ broker在JVM配置適當的內存量。此調整經過< system-Usage >元素的limit屬性進行。(最好從512MB開始,若是測試不夠再往上加),配置示例:
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit="512 mb"/>
</memoryUsage>
<storeUsage>
<storeUsage limit="10 gb" name="foo"/>
</storeUsage>
<tempUsage>
<tempUsage limit="1 gb"/>
</tempUsage>
</systemUsage></systemUsage>複製代碼
還應該下降每個鏈接的CPU負載,若是使用的OpenWire鏈接方式,禁用緊密編碼,不然會使得CPU過分緊張。
String uri = "failover://(tcp://localhost:61616?" + " wireFormat.tightEncodingEnabled=false)";
ConnectionFactory cf = new ActiveMQConnectionFactory(uri);複製代碼
前面研究的是broker怎麼調整去處理數千個鏈接,下面開始研究的是怎麼調整broker去處理數千個隊列。
默認隊列配置使用單獨的線程來將消息從消息存儲區分頁到隊列中,以便分發給感興趣的消息消費者。 對於大量隊列,建議經過爲全部隊列啓用optimize-Dispatch屬性來禁用此功能,
<destinationPolicy> <policyMap>
<policyEntries>
<policyEntry queue=">" optimizedDispatch="true"/>
</policyEntries>
</policyMap></destinationPolicy>複製代碼
爲了確保不只能夠擴展到數千個鏈接,並且還能夠擴展到數萬個隊列,使用JDBC消息存儲庫或更新和更快的KahaDB消息存儲庫。 KahaDB默認狀況下在ActiveMQ中啓用。
到目前爲止,咱們已經考慮了擴展鏈接,減小線程使用,並選擇正確的消息存儲。 調整用於擴展的ActiveMQ的示例配置如如下:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="amq-broker" dataDirectory="${activemq.base}/data">
<persistenceAdapter>
<kahaDB directory="${activemq.base}/data" journalMaxFileLength="32mb"/>
</persistenceAdapter>
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue=">" optimizedDispatch="true"/>
</policyEntries>
</policyMap>
</destinationPolicy>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit="512 mb"/>
</memoryUsage>
<storeUsage>
<storeUsage limit="10 gb" name="foo"/>
</storeUsage>
<tempUsage>
<tempUsage limit="1 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<transportConnector name="openwire" uri="nio://localhost:61616"/>
</transportConnectors></broker>複製代碼
2.水平擴展
除了擴展單個broker以外,還可使用networks來增長可用於應用程序的ActiveMQ broker的數量。 因爲networks會自動將消息傳遞給具備感興趣的消費者的鏈接broker,所以能夠將客戶端配置爲鏈接到一個broker集羣,隨機選擇一個來鏈接。
failover://(tcp://broker1:61616,tcp://broker2:61616)?randomize=true複製代碼
爲了確保隊列或持久主題訂閱者的消息不會在broker上孤立,須要將network配置爲使用dynamicOnly和低網絡prefetchSize。
<networkConnector uri="static://(tcp://remotehost:61617)"
name="bridge"
dynamicOnly="true"
prefetchSize="1"></networkConnector>複製代碼
使用network進行水平擴展會帶來更多的延遲,由於潛在的消息必須在分發給消費者以前經過多個broker。
另外一種替代部署提供了巨大的可擴展性和性能,但須要更多的應用規劃。 這種混合解決方案稱爲流量分區。
3.流量分區
客戶端流量分割是垂直和水平分割的混合。 一般不使用network,由於客戶端應用程序決定什麼流量應該到哪一個broker上。 客戶端應用程序必須維護多個JMS鏈接,並決定哪些JMS鏈接應用於哪些目標。
不直接使用network connection的優勢是,減小在brokers之間轉發消息的開銷。 須要平衡這與致使典型應用程序的額外複雜性。Fig10.8是流量分區的一個使用表明.
歡迎學Java和大數據的朋友們加入java架構交流: 855835163
羣內提供免費的架構資料還有:Java工程化、高性能及分佈式、高性能、深刻淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的免費直播講解 能夠進來一塊兒學習交流哦