ActiveMQ的集群與高可用

原文:
https://blog.csdn.net/zuolj/article/details/53116439

單純根據(jù)《ActiveMQ In Action(Manning-2011)》一書介紹的總結(jié),部分介紹可能已經(jīng)和官網(wǎng)不一弟胀。

一楷力、ActiveMQ的高可用性
ActiveMQ使用master-slave模式實現(xiàn)高可用性喊式,提供兩種實現(xiàn)主從模式的配置:shared nothing、shared storage(a relational database and a shared file system)

1.shared nothing master-slave

每一個broker(包括master和slave)都有自己的消息存儲區(qū)萧朝,這是最簡單的高可用性實現(xiàn)的辦法岔留。
master復(fù)制所有的消息指令給slave,復(fù)制的動作發(fā)生在master回復(fù)client消息已接收之前检柬。
slave broker會在啟動的時候去連接master献联,所以理想上,master broker應(yīng)該先啟動何址,slave broker 不會打開任何transports里逆,也就是說,slave broker不接收任何client請求和網(wǎng)絡(luò)連接用爪,除非master掛掉原押。slave通過檢測它與master之間的連接失敗而判定master掛掉。

shared nothing master-slave模式的處理過程:當一個生產(chǎn)者發(fā)送一個持久化消息到master之后偎血,master會復(fù)制該消息給slave诸衔,再返回接收應(yīng)答給生產(chǎn)者,生產(chǎn)者才能發(fā)送下一個消息烁巫。

當master broker掛掉后署隘,slave有兩個選擇:
1.關(guān)掉自己,因此亚隙,它只會保存master的狀態(tài)磁餐。
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屬性去設(shè)置master broker,強制master如果還沒與slave建立好連接旁赊,那么不會接受任何client的連接桦踊,另一個限制是,一個master只允許有一個slave终畅。

配置shared nothing master-slave
配置一個broker成為slave很簡單籍胯,配置一個masterConnector service:

<services>
    <!-- 
    remoteURI:master broker的監(jiān)聽地址
    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掛掉之后赠涮,無需手動干預(yù)去保持應(yīng)用的完整性子寓,另一個好處是,slave的數(shù)量不再有所限制笋除。
share nothing master-slave模式的配置有兩種:a relational database和file system-based storage.

shared database master-slave

當一個ActiveMQ broker使用關(guān)系型數(shù)據(jù)庫時斜友,它持有表的鎖以確保沒有其他broker同時訪問這個數(shù)據(jù)庫。多個broker同時運行并嘗試去訪問數(shù)據(jù)庫時垃它,只有第一個broker會連接成功并拿到鎖鲜屏,其他隨后到來的broker會一直poll直到它可以獲得鎖為止。這些處于polling狀態(tài)的broker国拇,被視為slave洛史,它們不會開啟任何傳輸連接或者網(wǎng)絡(luò)連接。
該配置中所有的broker可以使用同一份配置文件酱吝,這使得activemq啟動起來簡單得多也殖。

shared file system master-slave

它建議使用 KahaDB 消息存儲,但是對于消息存儲使用底層的共享的文件系統(tǒng)务热。當KahaDB消息存儲啟動時忆嗜,它將嘗試獲取文件鎖,以防止任何其他broker同時訪問基于文件的消息存儲崎岂。

二捆毫、ActiveMQ是如何在brokers之間傳遞消息
ActiveMQ中有一個概念:networks of brokers,它指的是連接ActiveMQ的消息代理在一起形成不同的拓撲結(jié)構(gòu)。
接下來就是分析brokers是如何在一個network中發(fā)現(xiàn)彼此且如何配置broker使其在network中合作等恐。

1.存儲和轉(zhuǎn)發(fā)(store and forward)
ActiveMQ的存儲和轉(zhuǎn)發(fā)概念意味著瘫析,消息在通過network轉(zhuǎn)發(fā)到其他broker之前,總是被存儲在本地broker中濒憋,也就是說,如果一條消息由于連接原因沒有被交付嫁审,比如說跋炕,正在重連,broker將能夠通過網(wǎng)絡(luò)連接將未交付的消息發(fā)送到遠程broker律适。默認情況下辐烂,network僅以單向方式操作遏插,如圖:

當然,這并不是說network只能單向操作纠修,如果想要雙向操作胳嘲,同樣可以在遠程broker中配置一個network connector指向本地的broker,或者直接指定創(chuàng)建的network connector為雙向duplex扣草。

當本地broker和遠程broker之間建立好一條network后了牛,遠程broker會將其所有持久和處于活動的消費者的目的地信息傳遞給本地broker,本地broker使用這些信息去判斷遠程broker對哪種消息感興趣辰妙,并轉(zhuǎn)發(fā)該類型消息給它鹰祸。

這里,書中舉了一個場景密浑,假如我們有多個超市需要連接到一個后臺辦公訂購系統(tǒng)蛙婴,這將很難靈活擴展新的超市,后臺辦公訂購系統(tǒng)不好掌控所有新加入的超市即遠程broker尔破。

給個圖示街图,這里想象超市和后臺之間有一個防火墻。(至于為什么這么想象懒构,我并不得知)注意到這里餐济,超市broker和back office之間的network是雙向的,超市broker的配置:

<networkConnectors>
    <networkConnector uri="static://(tcp://backoffice:61617)" 
        name="bridge" 
        duplex="true"
        conduitSubscriptions="true"
        decreaseNetworkConsumerPriority="false">
    </networkConnector>
</networkConnectors>

這里關(guān)于配置胆剧,主要注意一點是絮姆,配置的順序是很重要的,關(guān)于networks赞赖,persistence滚朵,transports的順序如下:

Networks——必須在消息存儲之前創(chuàng)建
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>

來一張,在大型開發(fā)場景下的高可用性和network配置結(jié)合:

2.Network發(fā)現(xiàn)機制
ActiveMQ提供兩種發(fā)現(xiàn)機制:

Dynamic——使用組播和會合方式搜索brokers
Static——通過一個URI列表配置brokers
使用組播發(fā)現(xiàn)的方式去創(chuàng)建network連接是最簡單粗暴的前域,當你啟動一個broker時辕近,它會通過組播IP去搜索其他的broker并創(chuàng)建network連接。配置方式如下:

<networkConnectors>
    <networkConnector uri="multicast://default"/>
</networkConnectors>

這里“default”表示這個broker屬于哪個組匿垄,建議使用唯一的名字去標識移宅,以免你的broker連接到其他你不知道的應(yīng)用代理上。
組播發(fā)現(xiàn)機制有一些限制椿疗,比如說不能控制哪些broker被發(fā)現(xiàn)漏峰,事實上,它通常局限于本地網(wǎng)段上去發(fā)現(xiàn)其他broker届榄,因為組播IP不通過路由器延伸浅乔。
關(guān)于第二種方式,static,事實上靖苇,在這之前的配置一直都是static席噩,只不過broker的URL列表有點少而已,

<networkConnectors>
    <networkConnector uri="static:(tcp://remote-master:61617,tcp://remote-slave:61617)"/>
</networkConnectors>

static的配置屬性:

3.Network配置
對于遠程broker現(xiàn)存在的目的地贤壁,可能沒有任何活動持久的訂閱者或消費者悼枢,因此,當network初始化連接到遠程broker時脾拆,遠程broker會讀取它現(xiàn)存目的地的消息馒索,并傳遞給本地broker,然后名船,本地broker也可以轉(zhuǎn)發(fā)那些目的地的消息绰上。
重要的是要注意,一個network將使用broker的名稱來代表遠程broker創(chuàng)建唯一的持久預(yù)訂代理包帚。 因此渔期,如果在稍后的時間點更改broker的名稱运吓,很可能會通過network丟失持久主題訂閱者的消息渴邦。 為避免這種情況,請確保為元素上的brokerName屬性使用唯一的名稱拘哨。 有關(guān)簡要示例谋梭,請參閱以下內(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
擴展使用ActiveMQ的應(yīng)用程序可能需要一些時間,需要一些努力产镐。 在本節(jié)中隘庄,將介紹三種技術(shù)來幫助完成此任務(wù)。首先是垂直擴展癣亚,單個broker用于數(shù)千個連接和隊列丑掺。然后將通過使用network水平擴展應(yīng)用程序來擴展到數(shù)萬個連接。 最后述雾,將研究流量分區(qū)街州,這將平衡擴展和性能,但會增加ActiveMQ應(yīng)用程序的復(fù)雜性玻孟。

1.垂直擴展
垂直擴展是一種用于增加單個ActiveMQ broker可以處理的連接數(shù)(因此增加負載)的技術(shù)唆缴。默認情況下,ActiveMQ broker設(shè)計為盡可能高效地移動消息黍翎,以確保低延遲和良好的性能面徽。但是我們可以做一些配置調(diào)整,以確保ActiveMQ broker可以處理大量的并發(fā)連接和大量的隊列匣掸。

默認情況下趟紊,ActiveMQ將使用阻塞I/O來處理傳輸連接质礼。 這導(dǎo)致每個連接使用一個線程。 我們可以在ActiveMQ broker上使用非阻塞I/O(而客戶端上仍然使用默認傳輸)來減少使用的線程數(shù)织阳。broker的非阻塞I/O配置如下:

<broker>
    <transportConnectors>
        <transportConnector name="nio" uri="nio://localhost:61616"/>
    </transportConnectors>
</broker>

除了每個連接使用一個線程來阻塞I/O外眶蕉,ActiveMQ broker可以使用線程為每個客戶端連接分派消息∵蠖悖可以通過將名為org.apache.activemq.UseDedicatedTaskRunner的系統(tǒng)屬性設(shè)置為false造挽,讓ActiveMQ使用線程池。

ACTIVEMQ_OPTS="-Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
確保ActiveMQ broker具有足夠的內(nèi)存來處理大量并發(fā)連接有兩步過程弄痹。
首先饭入,需要確保啟動ActiveMQ broker的JVM配置了足夠的內(nèi)存。

ACTIVEMQ_OPTS="-Xmx1024M -Dorg.apache.activemq.UseDedicatedTaskRunner=false"
1
第二肛真,確保專門為ActiveMQ broker在JVM配置適當?shù)膬?nèi)存量谐丢。此調(diào)整通過< 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>

還應(yīng)該降低每一個連接的CPU負載,如果使用的OpenWire連接方式历极,禁用緊密編碼窄瘟,否則會使得CPU過度緊張。

String uri = "failover://(tcp://localhost:61616?" + " wireFormat.tightEncodingEnabled=false)";
ConnectionFactory cf = new ActiveMQConnectionFactory(uri);

前面研究的是broker怎么調(diào)整去處理數(shù)千個連接趟卸,下面開始研究的是怎么調(diào)整broker去處理數(shù)千個隊列蹄葱。

默認隊列配置使用單獨的線程來將消息從消息存儲區(qū)分頁到隊列中,以便分發(fā)給感興趣的消息消費者锄列。 對于大量隊列图云,建議通過為所有隊列啟用optimize-Dispatch屬性來禁用此功能,

<destinationPolicy>
    <policyMap>
        <policyEntries>
            <policyEntry queue=">" optimizedDispatch="true"/>
        </policyEntries>
    </policyMap>
</destinationPolicy>

為了確保不僅可以擴展到數(shù)千個連接邻邮,而且還可以擴展到數(shù)萬個隊列竣况,使用JDBC消息存儲庫或更新和更快的KahaDB消息存儲庫。 KahaDB默認情況下在ActiveMQ中啟用饶囚。

到目前為止帕翻,我們已經(jīng)考慮了擴展連接,減少線程使用萝风,并選擇正確的消息存儲嘀掸。 調(diào)整用于擴展的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="&gt;" 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來增加可用于應(yīng)用程序的ActiveMQ broker的數(shù)量规惰。 由于networks會自動將消息傳遞給具有感興趣的消費者的連接broker睬塌,因此可以將客戶端配置為連接到一個broker集群,隨機選擇一個來連接。

failover://(tcp://broker1:61616,tcp://broker2:61616)?randomize=true

為了確保隊列或持久主題訂閱者的消息不會在broker上孤立揩晴,需要將network配置為使用dynamicOnly和低網(wǎng)絡(luò)prefetchSize勋陪。

<networkConnector uri="static://(tcp://remotehost:61617)"
    name="bridge"
    dynamicOnly="true"
    prefetchSize="1">
</networkConnector>

使用network進行水平擴展會帶來更多的延遲,因為潛在的消息必須在分發(fā)給消費者之前通過多個broker硫兰。

另一種替代部署提供了巨大的可擴展性和性能诅愚,但需要更多的應(yīng)用規(guī)劃。 這種混合解決方案稱為流量分區(qū)劫映。

3.流量分區(qū)
客戶端流量分割是垂直和水平分割的混合违孝。 通常不使用network,因為客戶端應(yīng)用程序決定什么流量應(yīng)該到哪個broker上泳赋。 客戶端應(yīng)用程序必須維護多個JMS連接雌桑,并決定哪些JMS連接應(yīng)用于哪些目標。
不直接使用network connection的優(yōu)點是祖今,減少在brokers之間轉(zhuǎn)發(fā)消息的開銷校坑。 需要平衡這與導(dǎo)致典型應(yīng)用程序的額外復(fù)雜性。Fig10.8是流量分區(qū)的一個使用代表:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末千诬,一起剝皮案震驚了整個濱河市耍目,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌大渤,老刑警劉巖制妄,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異泵三,居然都是意外死亡,警方通過查閱死者的電腦和手機衔掸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門烫幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敞映,你說我怎么就攤上這事较曼。” “怎么了振愿?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵捷犹,是天一觀的道長。 經(jīng)常有香客問我冕末,道長萍歉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任档桃,我火速辦了婚禮枪孩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己蔑舞,他們只是感情好拒担,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攻询,像睡著了一般从撼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钧栖,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天谋逻,我揣著相機與錄音,去河邊找鬼桐经。 笑死毁兆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的阴挣。 我是一名探鬼主播气堕,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畔咧!你這毒婦竟也來了茎芭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤誓沸,失蹤者是張志新(化名)和其女友劉穎梅桩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拜隧,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宿百,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了洪添。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垦页。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖干奢,靈堂內(nèi)的尸體忽然破棺而出痊焊,到底是詐尸還是另有隱情,我是刑警寧澤忿峻,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布薄啥,位于F島的核電站,受9級特大地震影響逛尚,放射性物質(zhì)發(fā)生泄漏垄惧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一黑低、第九天 我趴在偏房一處隱蔽的房頂上張望赘艳。 院中可真熱鬧酌毡,春花似錦、人聲如沸蕾管。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掰曾。三九已至旭蠕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旷坦,已是汗流浹背掏熬。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留秒梅,地道東北人旗芬。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像捆蜀,于是被迫代替她去往敵國和親疮丛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Redis Cluster Specification 1 設(shè)計目標和理由 1.1 Redis Cluster g...
    近路閱讀 4,230評論 0 12
  • 五辆它、轉(zhuǎn)機 轉(zhuǎn)眼誊薄,沈欣的畢業(yè)季即將來臨。 遠在上海的家人也早就知道她交了一位美國的高材生男友锰茉,很是欣慰呢蔫。 但是,父親...
    tanxiaotian閱讀 279評論 1 0
  • 過著過著怎么就變了飒筑,朋友談起片吊,談起他自己想寫的劇本,變成怎樣扬霜,變得越來越復(fù)雜定鸟、不通透,不明了著瓶。
    滇島少年閱讀 201評論 0 0