您好,登錄后才能下訂單哦!
一、ActiveMQ的高可用性
ActiveMQ使用master-slave模式實(shí)現(xiàn)高可用性,提供兩種實(shí)現(xiàn)主從模式的配置:shared nothing、shared storage(a relational database and a shared file system)
1.shared nothing master-slave
每一個(gè)broker(包括master和slave)都有自己的消息存儲(chǔ)區(qū),這是最簡單的高可用性實(shí)現(xiàn)的辦法。
master復(fù)制所有的消息指令給slave,復(fù)制的動(dòng)作發(fā)生在master回復(fù)client消息已接收之前。
slave broker會(huì)在啟動(dòng)的時(shí)候去連接master,所以理想上,master broker應(yīng)該先啟動(dòng),slave broker 不會(huì)打開任何transports,也就是說,slave broker不接收任何client請(qǐng)求和網(wǎng)絡(luò)連接,除非master掛掉。slave通過檢測它與master之間的連接失敗而判定master掛掉。
shared nothing master-slave模式的處理過程:當(dāng)一個(gè)生產(chǎn)者發(fā)送一個(gè)持久化消息到master之后,master會(huì)復(fù)制該消息給slave,再返回接收應(yīng)答給生產(chǎn)者,生產(chǎn)者才能發(fā)送下一個(gè)消息。
當(dāng)master broker掛掉后,slave有兩個(gè)選擇:
1.關(guān)掉自己,因此,它只會(huì)保存master的狀態(tài)。
2.打開transports并且初始化所有的network connections,因此,該slave自動(dòng)成為新的master。
如果slave broker成為新的master broker,所有的client可以通過failover機(jī)制去連接上新的master。在默認(rèn)的client連接中,failover傳輸機(jī)制皆可以連接到master和slave:
failover://(tcp://masterhost:61616,tcp://slavehost:61616)?randomize=false
不過,使用shared nothing master-slave也有限制,如果client先連上master進(jìn)行工作,而slave還沒與master進(jìn)行連接,master掛掉,消息很可能會(huì)丟失。ActiveMQ提供了一個(gè)waitForSlave屬性去設(shè)置master broker,強(qiáng)制master如果還沒與slave建立好連接,那么不會(huì)接受任何client的連接,另一個(gè)限制是,一個(gè)master只允許有一個(gè)slave。
配置shared nothing master-slave
配置一個(gè)broker成為slave很簡單,配置一個(gè)masterConnector service:
<services>
<!--
remoteURI:master broker的監(jiān)聽地址
userName:Optional,如果master需要身份驗(yàn)證
password:Optional,如果master需要身份驗(yàn)證
-->
<masterConnector remoteURI="tcp://remotehost:62001" userName="" password=""/></services>
2.shared storage master-slave
share nothing master-slave模式下,每一個(gè)broker都獨(dú)自維護(hù)自己的storage,而shared storage master-slave模式允許多個(gè)broker共享存儲(chǔ),但同一個(gè)時(shí)刻只有一個(gè)broker是存活的。shared storage master-slave的好處在于,它確保了當(dāng)master掛掉之后,無需手動(dòng)干預(yù)去保持應(yīng)用的完整性,另一個(gè)好處是,slave的數(shù)量不再有所限制。
share nothing master-slave模式的配置有兩種:a relational database和file system-based storage.
shared database master-slave
當(dāng)一個(gè)ActiveMQ broker使用關(guān)系型數(shù)據(jù)庫時(shí),它持有表的鎖以確保沒有其他broker同時(shí)訪問這個(gè)數(shù)據(jù)庫。多個(gè)broker同時(shí)運(yùn)行并嘗試去訪問數(shù)據(jù)庫時(shí),只有第一個(gè)broker會(huì)連接成功并拿到鎖,其他隨后到來的broker會(huì)一直poll直到它可以獲得鎖為止。這些處于polling狀態(tài)的broker,被視為slave,它們不會(huì)開啟任何傳輸連接或者網(wǎng)絡(luò)連接。
該配置中所有的broker可以使用同一份配置文件,這使得activemq啟動(dòng)起來簡單得多。
shared file system master-slave
它建議使用 KahaDB 消息存儲(chǔ),但是對(duì)于消息存儲(chǔ)使用底層的共享的文件系統(tǒng)。當(dāng)KahaDB消息存儲(chǔ)啟動(dòng)時(shí),它將嘗試獲取文件鎖,以防止任何其他broker同時(shí)訪問基于文件的消息存儲(chǔ)。
二、ActiveMQ是如何在brokers之間傳遞消息
ActiveMQ中有一個(gè)概念:networks of brokers,它指的是連接ActiveMQ的消息代理在一起形成不同的拓?fù)浣Y(jié)構(gòu)。
接下來就是分析brokers是如何在一個(gè)network中發(fā)現(xiàn)彼此且如何配置broker使其在network中合作。
1.存儲(chǔ)和轉(zhuǎn)發(fā)(store and forward)
ActiveMQ的存儲(chǔ)和轉(zhuǎn)發(fā)概念意味著,消息在通過network轉(zhuǎn)發(fā)到其他broker之前,總是被存儲(chǔ)在本地broker中,也就是說,如果一條消息由于連接原因沒有被交付,比如說,正在重連,broker將能夠通過網(wǎng)絡(luò)連接將未交付的消息發(fā)送到遠(yuǎn)程broker。默認(rèn)情況下,network僅以單向方式操作,如圖:
當(dāng)然,這并不是說network只能單向操作,如果想要雙向操作,同樣可以在遠(yuǎn)程broker中配置一個(gè)network connector指向本地的broker,或者直接指定創(chuàng)建的network connector為雙向duplex。
當(dāng)本地broker和遠(yuǎn)程broker之間建立好一條network后,遠(yuǎn)程broker會(huì)將其所有持久和處于活動(dòng)的消費(fèi)者的目的地信息傳遞給本地broker,本地broker使用這些信息去判斷遠(yuǎn)程broker對(duì)哪種消息感興趣,并轉(zhuǎn)發(fā)該類型消息給它。
這里,書中舉了一個(gè)場景,假如我們有多個(gè)超市需要連接到一個(gè)后臺(tái)辦公訂購系統(tǒng),這將很難靈活擴(kuò)展新的超市,后臺(tái)辦公訂購系統(tǒng)不好掌控所有新加入的超市即遠(yuǎn)程broker。
給個(gè)圖示,這里想象超市和后臺(tái)之間有一個(gè)防火墻。(至于為什么這么想象,我并不得知)注意到這里,超市broker和back office之間的network是雙向的,超市broker的配置:
<networkConnectors>
<networkConnector uri="static://(tcp://backoffice:61617)"
name="bridge"
duplex="true"
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false">
</networkConnector></networkConnectors>
這里關(guān)于配置,主要注意一點(diǎn)是,配置的順序是很重要的,關(guān)于networks,persistence,transports的順序如下:
Networks——必須在消息存儲(chǔ)之前創(chuàng)建
Message store——必須在傳輸配置好之前配置完
Transports——必須在broker配置的最后
舉個(gè)例子:
<?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>
來一張,在大型開發(fā)場景下的高可用性和network配置結(jié)合:
2.Network發(fā)現(xiàn)機(jī)制
ActiveMQ提供兩種發(fā)現(xiàn)機(jī)制:
Dynamic——使用組播和會(huì)合方式搜索brokers
Static——通過一個(gè)URI列表配置brokers
使用組播發(fā)現(xiàn)的方式去創(chuàng)建network連接是最簡單粗暴的,當(dāng)你啟動(dòng)一個(gè)broker時(shí),它會(huì)通過組播IP去搜索其他的broker并創(chuàng)建network連接。配置方式如下:
<networkConnectors> <networkConnector uri="multicast://default"/></networkConnectors>
這里“default”表示這個(gè)broker屬于哪個(gè)組,建議使用唯一的名字去標(biāo)識(shí),以免你的broker連接到其他你不知道的應(yīng)用代理上。
組播發(fā)現(xiàn)機(jī)制有一些限制,比如說不能控制哪些broker被發(fā)現(xiàn),事實(shí)上,它通常局限于本地網(wǎng)段上去發(fā)現(xiàn)其他broker,因?yàn)榻M播IP不通過路由器延伸。
關(guān)于第二種方式,static,事實(shí)上,在這之前的配置一直都是static,只不過broker的URL列表有點(diǎn)少而已,
<networkConnectors> <networkConnector uri="static:(tcp://remote-master:61617,tcp://remote-slave:61617)"/></networkConnectors>
static的配置屬性:
3.Network配置
對(duì)于遠(yuǎn)程broker現(xiàn)存在的目的地,可能沒有任何活動(dòng)持久的訂閱者或消費(fèi)者,因此,當(dāng)network初始化連接到遠(yuǎn)程broker時(shí),遠(yuǎn)程broker會(huì)讀取它現(xiàn)存目的地的消息,并傳遞給本地broker,然后,本地broker也可以轉(zhuǎn)發(fā)那些目的地的消息。
重要的是要注意,一個(gè)network將使用broker的名稱來代表遠(yuǎn)程broker創(chuàng)建唯一的持久預(yù)訂代理。 因此,如果在稍后的時(shí)間點(diǎn)更改broker的名稱,很可能會(huì)通過network丟失持久主題訂閱者的消息。 為避免這種情況,請(qǐng)確保為元素上的brokerName屬性使用唯一的名稱。 有關(guān)簡要示例,請(qǐng)參閱以下內(nèi)容:
<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>
關(guān)于Network配置還有很多,不一一列舉了。
三、為大量并發(fā)應(yīng)用程序部署ActiveMQ
擴(kuò)展使用ActiveMQ的應(yīng)用程序可能需要一些時(shí)間,需要一些努力。 在本節(jié)中,將介紹三種技術(shù)來幫助完成此任務(wù)。首先是垂直擴(kuò)展,單個(gè)broker用于數(shù)千個(gè)連接和隊(duì)列。然后將通過使用network水平擴(kuò)展應(yīng)用程序來擴(kuò)展到數(shù)萬個(gè)連接。 最后,將研究流量分區(qū),這將平衡擴(kuò)展和性能,但會(huì)增加ActiveMQ應(yīng)用程序的復(fù)雜性。
1.垂直擴(kuò)展
垂直擴(kuò)展是一種用于增加單個(gè)ActiveMQ broker可以處理的連接數(shù)(因此增加負(fù)載)的技術(shù)。默認(rèn)情況下,ActiveMQ broker設(shè)計(jì)為盡可能高效地移動(dòng)消息,以確保低延遲和良好的性能。但是我們可以做一些配置調(diào)整,以確保ActiveMQ broker可以處理大量的并發(fā)連接和大量的隊(duì)列。
默認(rèn)情況下,ActiveMQ將使用阻塞I/O來處理傳輸連接。 這導(dǎo)致每個(gè)連接使用一個(gè)線程。 我們可以在ActiveMQ broker上使用非阻塞I/O(而客戶端上仍然使用默認(rèn)傳輸)來減少使用的線程數(shù)。broker的非阻塞I/O配置如下:
<broker> <transportConnectors>
<transportConnector name="nio" uri="nio://localhost:61616"/>
</transportConnectors></broker>
除了每個(gè)連接使用一個(gè)線程來阻塞I/O外,ActiveMQ broker可以使用線程為每個(gè)客戶端連接分派消息??梢酝ㄟ^將名為org.apache.activemq.UseDedicatedTaskRunner的系統(tǒng)屬性設(shè)置為false,讓ActiveMQ使用線程池。
ACTIVEMQ_OPTS="-Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
確保ActiveMQ broker具有足夠的內(nèi)存來處理大量并發(fā)連接有兩步過程。
首先,需要確保啟動(dòng)ActiveMQ broker的JVM配置了足夠的內(nèi)存。
ACTIVEMQ_OPTS="-Xmx1024M -Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
第二,確保專門為ActiveMQ broker在JVM配置適當(dāng)?shù)膬?nèi)存量。此調(diào)整通過< system-Usage >元素的limit屬性進(jìn)行。(最好從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>
還應(yīng)該降低每一個(gè)連接的CPU負(fù)載,如果使用的OpenWire連接方式,禁用緊密編碼,否則會(huì)使得CPU過度緊張。
String uri = "failover://(tcp://localhost:61616?" + " wireFormat.tightEncodingEnabled=false)";
ConnectionFactory cf = new ActiveMQConnectionFactory(uri);
前面研究的是broker怎么調(diào)整去處理數(shù)千個(gè)連接,下面開始研究的是怎么調(diào)整broker去處理數(shù)千個(gè)隊(duì)列。
默認(rèn)隊(duì)列配置使用單獨(dú)的線程來將消息從消息存儲(chǔ)區(qū)分頁到隊(duì)列中,以便分發(fā)給感興趣的消息消費(fèi)者。 對(duì)于大量隊(duì)列,建議通過為所有隊(duì)列啟用optimize-Dispatch屬性來禁用此功能,
<destinationPolicy> <policyMap>
<policyEntries>
<policyEntry queue=">" optimizedDispatch="true"/>
</policyEntries>
</policyMap></destinationPolicy>
為了確保不僅可以擴(kuò)展到數(shù)千個(gè)連接,而且還可以擴(kuò)展到數(shù)萬個(gè)隊(duì)列,使用JDBC消息存儲(chǔ)庫或更新和更快的KahaDB消息存儲(chǔ)庫。 KahaDB默認(rèn)情況下在ActiveMQ中啟用。
到目前為止,我們已經(jīng)考慮了擴(kuò)展連接,減少線程使用,并選擇正確的消息存儲(chǔ)。 調(diào)整用于擴(kuò)展的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.水平擴(kuò)展
除了擴(kuò)展單個(gè)broker之外,還可以使用networks來增加可用于應(yīng)用程序的ActiveMQ broker的數(shù)量。 由于networks會(huì)自動(dòng)將消息傳遞給具有感興趣的消費(fèi)者的連接broker,因此可以將客戶端配置為連接到一個(gè)broker集群,隨機(jī)選擇一個(gè)來連接。
failover://(tcp://broker1:61616,tcp://broker2:61616)?randomize=true
為了確保隊(duì)列或持久主題訂閱者的消息不會(huì)在broker上孤立,需要將network配置為使用dynamicOnly和低網(wǎng)絡(luò)prefetchSize。
<networkConnector uri="static://(tcp://remotehost:61617)"
name="bridge"
dynamicOnly="true"
prefetchSize="1"></networkConnector>
使用network進(jìn)行水平擴(kuò)展會(huì)帶來更多的延遲,因?yàn)闈撛诘南⒈仨氃诜职l(fā)給消費(fèi)者之前通過多個(gè)broker。
另一種替代部署提供了巨大的可擴(kuò)展性和性能,但需要更多的應(yīng)用規(guī)劃。 這種混合解決方案稱為流量分區(qū)。
3.流量分區(qū)
客戶端流量分割是垂直和水平分割的混合。 通常不使用network,因?yàn)榭蛻舳藨?yīng)用程序決定什么流量應(yīng)該到哪個(gè)broker上。 客戶端應(yīng)用程序必須維護(hù)多個(gè)JMS連接,并決定哪些JMS連接應(yīng)用于哪些目標(biāo)。
不直接使用network connection的優(yōu)點(diǎn)是,減少在brokers之間轉(zhuǎn)發(fā)消息的開銷。 需要平衡這與導(dǎo)致典型應(yīng)用程序的額外復(fù)雜性。Fig10.8是流量分區(qū)的一個(gè)使用代表.
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。