溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

發(fā)布時(shí)間:2021-11-15 14:14:24 來(lái)源:億速云 閱讀:123 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1、架構(gòu)設(shè)計(jì)概要

ActiveMQ提供兩種可供實(shí)施的架構(gòu)模型:“M-S”和“network  bridge”;其中“M-S”是HA方案,“網(wǎng)絡(luò)轉(zhuǎn)發(fā)橋”用于實(shí)現(xiàn)“分布式隊(duì)列”。

1.1、M-S

Master-Slave模型下,通常需要2+個(gè)ActiveMQ實(shí)例,任何時(shí)候只有一個(gè)實(shí)例為Master,向Client提供”生產(chǎn)”、“消費(fèi)”服務(wù),Slaves用于做backup或者等待Failover時(shí)角色接管。

M-S模型是最通用的架構(gòu)模型,它提供了“高可用”特性,當(dāng)Master失效后,Slaves之一提升為master繼續(xù)提供服務(wù),且Failover之后消息仍然可以恢復(fù)。(根據(jù)底層存儲(chǔ)不同,有可能會(huì)有消息的丟失)。

有以下兩方面要點(diǎn):

第一,M-S架構(gòu)中,涉及到選舉問(wèn)題,選舉的首要條件就是需要有“排它鎖”的支持。排它鎖,可以有共享文件鎖、JDBC數(shù)據(jù)庫(kù)排它鎖、JDBC鎖租約、zookeeper分布式鎖等方式實(shí)現(xiàn)。這取決你的底層存儲(chǔ)的機(jī)制。

第二,M-S架構(gòu)中,消息存儲(chǔ)的機(jī)制有多種,“共享文件存儲(chǔ)”、“JDBC”存儲(chǔ)、“非共享存儲(chǔ)”等。不同存儲(chǔ)機(jī)制,各有優(yōu)缺點(diǎn)。在使用的時(shí)候一定要權(quán)衡。

1.2、網(wǎng)絡(luò)轉(zhuǎn)發(fā)橋(network bridge)

無(wú)論如何,一組M-S所能承載的消息量、Client并發(fā)級(jí)別總是有限的,當(dāng)我們的消息規(guī)模達(dá)到單機(jī)的上限時(shí),就應(yīng)該使用基于集群的方式,將消息、Client進(jìn)行分布式和負(fù)載均衡。

ActiveMQ提供了“網(wǎng)絡(luò)轉(zhuǎn)發(fā)橋”模式,核心思想是:

1、集群中多個(gè)broker之間,通過(guò)“連接”互相通信,并將消息在多個(gè)Broker之間轉(zhuǎn)發(fā)和存儲(chǔ),提供存儲(chǔ)層面的“負(fù)載均衡”。

2、根據(jù)Client的并發(fā)情況,對(duì)Client進(jìn)行動(dòng)態(tài)平衡,最終實(shí)現(xiàn)支持大規(guī)模生產(chǎn)者、消費(fèi)者。

這和Kafka的核心思想是相似的。

2、M-S架構(gòu)設(shè)計(jì)詳解

2.1、非共享存儲(chǔ)模式

集群中有2+個(gè)ActiveMQ實(shí)例,每個(gè)實(shí)例單獨(dú)存儲(chǔ)數(shù)據(jù),Master將消息保存在本地后,并將消息以異步的方式轉(zhuǎn)發(fā)給Slaves。

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

Master和slaves獨(dú)立部署,各自負(fù)責(zé)自己的存儲(chǔ),Master與slaves之間通過(guò)“network  connector”連接,通常是Master單向與slaves建立連接。master上接收到的消息將會(huì)全量轉(zhuǎn)發(fā)給slaves。

有下面幾個(gè)要點(diǎn):

1)任何時(shí)候只有Master向Clients提供服務(wù),slaves僅作backup。古老的影子節(jié)點(diǎn)方式。

2)slaves上存儲(chǔ)的消息,有短暫的延遲。

3)master永遠(yuǎn)是master,當(dāng)master失效時(shí),我們不能隨意進(jìn)行角色切換,最佳實(shí)施方式就是重啟master,只有當(dāng)master物理失效時(shí)才會(huì)考慮將slave提升為master。(這個(gè)真是弱爆了)

4)當(dāng)slaves需要提升為master時(shí),應(yīng)該確保此slaves的消息是最新的。

5)如果slaves離線,那么在重啟slaves之前,還應(yīng)該將master的數(shù)據(jù)手動(dòng)同步給slaves。否則slave離線期間的數(shù)據(jù),將不會(huì)在slaves上復(fù)現(xiàn)。

6)Client端不支持failover協(xié)議;即Client只會(huì)與master建立連接。

這種架構(gòu),是最原始的架構(gòu),易于實(shí)時(shí),但是問(wèn)題比較嚴(yán)重,缺乏Failover機(jī)制,消息的可靠性我們無(wú)法完全保障,因?yàn)閙aster與slaves角色切換沒(méi)有仲裁者、或者說(shuō)缺少分布式排它鎖機(jī)制。在Production環(huán)境中,不建議采用,如果你能容忍failover期間SLA水平降級(jí)的話,也可以作為備選。

2.2、共享文件存儲(chǔ)

即采用SAN(GFS)技術(shù),基于網(wǎng)絡(luò)的全局共享文件系統(tǒng)模式(真是一個(gè)名次制造機(jī)器),這種架構(gòu)簡(jiǎn)單易用,但是可架構(gòu)、可設(shè)計(jì)的能力較弱,在Production環(huán)境下酌情采用。

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

SAN存儲(chǔ),可以參考GFS。其中master和slaves配置保持一致,每個(gè)broker都需要有唯一的brokerName;broker實(shí)例在啟動(dòng)時(shí)首先通過(guò)SAN獲取文件系統(tǒng)的排它鎖,獲取lock的實(shí)例將成為master,其他brokers將等待lock、并間歇性的嘗試獲取鎖,slaves不提供Clients服務(wù);因?yàn)閎rokers將數(shù)據(jù)寫(xiě)入GFS,所以在failover之后,新的master獲取的數(shù)據(jù)視圖仍然與原master保持一致,畢竟GFS是全局的共享文件系統(tǒng)。

我們通常使用kahaDB作為存儲(chǔ)引擎,即使用日志文件方式;kahaDB的存儲(chǔ)效率非常的高,TPS可以高達(dá)2W左右,是一種高效的、數(shù)據(jù)恢復(fù)能力強(qiáng)的存儲(chǔ)機(jī)制。

這種架構(gòu)模式下,支持failover,當(dāng)master失效后,Clients能夠通過(guò)failover協(xié)議與新的master重連,服務(wù)中斷時(shí)間很短。因?yàn)榛贕FS存儲(chǔ),所以數(shù)據(jù)總是保存在遠(yuǎn)端共享存儲(chǔ)區(qū)域,所以不存在數(shù)據(jù)丟失的問(wèn)題。

唯一的問(wèn)題,就是GFS(SAN)的穩(wěn)定性問(wèn)題。這一點(diǎn)需要確定,SAN區(qū)域中的節(jié)點(diǎn)之間網(wǎng)絡(luò)通信必須穩(wěn)定且高效。(自己搭建比如NFS服務(wù),或者基于AWS  EFS)。

這不過(guò)是把一個(gè)問(wèn)題轉(zhuǎn)移到另外一個(gè)組件上而已。

2.3、基于JDBC共享存儲(chǔ)

我們可以將支持JDBC的數(shù)據(jù)庫(kù)作為共享存儲(chǔ)層,即master將數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù),本地不保存任何數(shù)據(jù),在failover期間,slave提升為master之后,新master即可從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),這也意味著在整個(gè)周期中,master與slaves的數(shù)據(jù)視圖是一致的(同SAN架構(gòu)),所以數(shù)據(jù)的恢復(fù)能力和一致性是可以保障的,也不存在數(shù)據(jù)丟失的情況(在存儲(chǔ)層)。

但是JDBC存儲(chǔ)機(jī)制,性能實(shí)在是太低,與kahaDB這種基于日志存儲(chǔ)層相比,性能相差近10倍左右。

Oh my god。不過(guò)在一些低并發(fā),純粹解耦的場(chǎng)景是可以的。用在高并發(fā)互聯(lián)網(wǎng)就是找死(互聯(lián)網(wǎng)不一定意味著就是高并發(fā)的)。

如果你的業(yè)務(wù)需求,表明數(shù)據(jù)丟失是難以容忍的、且SLA水平很高很高,那么JDBC或許是你最好的選擇。

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

既然JDBC數(shù)據(jù)庫(kù)為最終存儲(chǔ)層,那么我們很多時(shí)候需要關(guān)注數(shù)據(jù)庫(kù)的可用性問(wèn)題,比如數(shù)據(jù)庫(kù)基于M-S模式等;如果數(shù)據(jù)庫(kù)失效,將導(dǎo)致ActiveMQ集群不可用。

JDBC存儲(chǔ)面臨最大的問(wèn)題就是“TPS”(吞吐能力),確實(shí)比kahaDB低數(shù)倍,如果你的業(yè)務(wù)存在高峰,“削峰”的策略可以首先將消息寫(xiě)入本地文件(然后異步同步給AcitveMQ  Broker)。

這個(gè)時(shí)候我總是有個(gè)疑問(wèn)。直接使用數(shù)據(jù)庫(kù)就好了,您廢這么大勁上個(gè)ActiveMQ又是何苦呢??赡苁菫榱嗽O(shè)計(jì)而設(shè)計(jì)吧。

3、network bridges模式架構(gòu)

這種架構(gòu)模式,主要是應(yīng)對(duì)大規(guī)模Clients、高密度的消息增量的場(chǎng)景;它將以集群的模式,承載較大數(shù)據(jù)量的應(yīng)用。

它有下面的要求和特點(diǎn)。

1)有大量Producers、Consumers客戶端接入。只所以如此,或許是因?yàn)橄⑼ǖ?Topic,Queue)在水平擴(kuò)張的方向上,已經(jīng)沒(méi)有太大的拆分可能性。所以一股腦擠在一塊。

2)或許消息的增量,是很龐大的,特別是一些“非持久化消息”。我們寄希望于構(gòu)建“分布式隊(duì)列”架構(gòu)。也就是其他系統(tǒng)解決不了的問(wèn)題,希望消息隊(duì)列能夠緩沖一下。

3)因?yàn)榧阂?guī)模較大,我們可能允許集群某些節(jié)點(diǎn)短暫的離線,但數(shù)據(jù)恢復(fù)機(jī)制仍然需要提供,總體而言,集群仍然提供較高的可用性。

4)集群支持Clients的負(fù)載均衡,比如有多個(gè)producers時(shí),這些producers會(huì)被動(dòng)態(tài)的在多個(gè)brokers之間平衡。否則分配不均就會(huì)造成風(fēng)險(xiǎn)。

5)支持failover,即當(dāng)某個(gè)broker失效時(shí),Clients可以與其他brokers重連;當(dāng)集群中有的新的brokers加入時(shí),集群的拓?fù)湟部梢詣?dòng)態(tài)的通知給Clients。這個(gè)是運(yùn)維人員最喜歡的,誰(shuí)也不想大半夜起床搗鼓機(jī)器。

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

集群有多個(gè)子Groups構(gòu)成,每個(gè)Group為M-S模式、共享存儲(chǔ);多個(gè)Groups之間基于“network  Connector”建立連接(masterslave協(xié)議),通常為雙向連接,所有的Groups之間彼此相連,Groups之間形成“訂閱”關(guān)系,比如G2在邏輯上為G1的訂閱者(訂閱的策略是根據(jù)各個(gè)Broker上消費(fèi)者的Destination列表進(jìn)行分類),消息的轉(zhuǎn)發(fā)原理也是基于此。

對(duì)于Client而言,仍然支持failover,failover協(xié)議中可以包含集群中“多數(shù)派”的節(jié)點(diǎn)地址。

對(duì)于Topic訂閱者的消息,將會(huì)在所有Group中復(fù)制存儲(chǔ);對(duì)于Queue的消息,將會(huì)在brokers之間轉(zhuǎn)發(fā),并最終到達(dá)Consumer所在的節(jié)點(diǎn)。

Producers和Consumers可以與任何Group中的Master建立連接并進(jìn)行消息通信,當(dāng)Brokers集群拓?fù)渥兓瘯r(shí)、Producers或Consumers的個(gè)數(shù)變化時(shí),將會(huì)動(dòng)態(tài)平衡Clients的連接位置。Brokers之間通過(guò)“advisory”機(jī)制來(lái)同步Clients的連接信息,比如新的Consumers加入,Broker將會(huì)發(fā)送advisory消息(內(nèi)部的通道)通知其他brokers。

集群模式提供了較好的可用性擔(dān)保能力,在某些特性上或許需要權(quán)衡,比如Queue消息的有序性將會(huì)打破,因?yàn)橥粋€(gè)Queue的多個(gè)Consumer可能位于不同的Group上,如果某個(gè)Group實(shí)現(xiàn),那么保存在其上的消息只有當(dāng)其恢復(fù)后才能對(duì)Clients可見(jiàn)。

4、性能評(píng)估

綜上所述,在Production環(huán)境中,我們能夠真正意義上采用的架構(gòu),只有三種:

1)基于JDBC的共享數(shù)據(jù)庫(kù)模式:HA架構(gòu),單一Group,Group中包含一個(gè)master和任意多個(gè)slaves;所有Brokers之間通過(guò)遠(yuǎn)端共享數(shù)據(jù)庫(kù)存取數(shù)據(jù)。對(duì)客戶端而言支持Failover協(xié)議。

2)基于Network  Bridge構(gòu)建分布式消息集群:Cluster架構(gòu),集群中有多個(gè)Group,每個(gè)Group均為M-S架構(gòu)、基于共享存儲(chǔ);對(duì)于Clients而言,支持負(fù)載均衡和Failover;消息從Producer出發(fā),到達(dá)Broker節(jié)點(diǎn),Broker根據(jù)“集群中Consumers分布”,將消息轉(zhuǎn)發(fā)給Consumers所在的Broker上,實(shí)現(xiàn)消息的按需流動(dòng)。

3)基于Network  Bridge的簡(jiǎn)化改造:與2)類似,但是每個(gè)“Group”只有一個(gè)Broker節(jié)點(diǎn),此Broker基于kahaDB本地文件存儲(chǔ),即相對(duì)于2)Group缺少了HA特性;當(dāng)Broker節(jié)點(diǎn)失效時(shí),其上的消息將不可見(jiàn)、直到Broker恢復(fù)正常。這種簡(jiǎn)化版的架構(gòu)模式,通過(guò)增加機(jī)器的數(shù)量、細(xì)分消息的分布,來(lái)降低數(shù)據(jù)影響故障影響的規(guī)模,因?yàn)槠浠趉ahaDB本地日志存儲(chǔ),所以性能很高。

4.1、共享JDBC測(cè)試結(jié)果

生產(chǎn)端配置。

Producer端(壓力輸出機(jī)器):數(shù)量:4臺(tái)       硬件配置:16Core、32G,云主機(jī)       軟件配置:JDK 1.8,JVM 24G       并發(fā)與線程:32并發(fā)線程,連接池為128,發(fā)送文本消息,每個(gè)消息128個(gè)字符實(shí)體。消息:持久化,Queue,非事務(wù)

Broker端配置。

Broker端(壓力承載)       數(shù)量:2臺(tái)       硬件配置:16Core、32G,云主機(jī)       軟件配置:JDK 1.8,JVM 24G       架構(gòu)模式:M-S模式,開(kāi)啟異步轉(zhuǎn)發(fā)、關(guān)閉FlowControl,數(shù)據(jù)庫(kù)連接池為1024

存儲(chǔ)層配置。

數(shù)據(jù)庫(kù)(存儲(chǔ)層)       數(shù)量:2臺(tái)       硬件配置:16Core、32G,SSD(IOPS 3000),云主機(jī)       架構(gòu)模式:M-S       數(shù)據(jù)庫(kù):MySQL

測(cè)試結(jié)果:

1、消息生產(chǎn)效率:1500 TPS

2、Broker負(fù)載情況:CPU 30%,內(nèi)存使用率11%

3、MySQL負(fù)載情況:CPU 46%,IO_WAIT 25%

結(jié)論:

1、基于共享JDBC存儲(chǔ)架構(gòu),性能確實(shí)較低。

2、影響性能的關(guān)鍵點(diǎn),就是數(shù)據(jù)庫(kù)的并發(fā)IO能力,當(dāng)TPS在1800左右時(shí),數(shù)據(jù)庫(kù)的磁盤(pán)(包括slave同步IO)已經(jīng)出現(xiàn)較高的IO_WAIT。

3、通過(guò)升級(jí)磁盤(pán)、增加IOPS,可以有效提升TPS指標(biāo),建議同時(shí)提高CPU的個(gè)數(shù)。

打算采用數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)HA的同學(xué)們,你們看到這操蛋的TPS了么?

4.2、基于非共享文件存儲(chǔ)的測(cè)試結(jié)果

測(cè)試單個(gè)ActiveMQ,基于kahaDB存儲(chǔ),kahaDB分為兩種數(shù)據(jù)刷盤(pán)模式:

1)逐條消息刷盤(pán)

2)每隔一秒刷盤(pán)

<persistenceAdapter>       <kahaDB directory="${activemq.data}/kahadb" journalDiskSyncStrategy="periodic" journalDiskSyncInterval="2000"/>  </persistenceAdapter>

壓力測(cè)試環(huán)境與1)保持一致,只是ActiveMQ的機(jī)器的磁盤(pán)更換為:SSD (600 IOPS)。

測(cè)試結(jié)果:

1)逐條刷新磁盤(pán)

TPS:660

Broker IO_WAIT:19%

2)每隔一秒刷新磁盤(pán)

TPS:9800

Broker IO_WAIT:1.6% (原則上優(yōu)化磁盤(pán)和IOPS等,應(yīng)該還能提升)

由此可見(jiàn),基于日志文件的存儲(chǔ)性能比JDBC高了接近5倍,其中逐條刷盤(pán)策略,消息的可靠性是最高的,但是性能卻低于JDBC。如果基于“每隔一秒刷盤(pán)”策略,在極端情況下,可能導(dǎo)致最近一秒的數(shù)據(jù)丟失。

還不錯(cuò),但離著kafka這樣的MQ還遠(yuǎn)著呢。

4.3、基于轉(zhuǎn)發(fā)橋的測(cè)試結(jié)果

基于轉(zhuǎn)發(fā)橋的架構(gòu),實(shí)施成本較高,維護(hù)成本較高,架構(gòu)復(fù)雜度也相對(duì)較大。本人根據(jù)實(shí)踐經(jīng)驗(yàn),不推薦使用此模式。如果你希望嘗試,也無(wú)妨,畢竟它是ActiveMQ官方推薦的“分布式隊(duì)列實(shí)現(xiàn)機(jī)制”,從原理上它可以支持較大規(guī)模的消息存儲(chǔ)。

但是,我有更輕量級(jí)的,干么用你呢?

4.4、優(yōu)秀實(shí)踐

所以本優(yōu)秀實(shí)踐是在以上測(cè)試的基礎(chǔ)上得來(lái)的。

ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析

如果我們最終不得不面對(duì)“海量消息”的存儲(chǔ),在按照業(yè)務(wù)進(jìn)行隊(duì)列拆分之后,仍然需要面臨某個(gè)單純業(yè)務(wù)的消息量是“單個(gè)M-S架構(gòu)”無(wú)法滿足的。而我們又不愿意承擔(dān)Cluster模式復(fù)雜度所帶來(lái)的潛在問(wèn)題,此時(shí),可以采用比較通用的“邏輯分布式”機(jī)制。

1)構(gòu)建多個(gè)M-S組,但是每個(gè)Group之間在物理上沒(méi)有關(guān)聯(lián),即它們之間互不通信,且不共享存儲(chǔ)。

2)在Producer的客戶端,增加“router”層, 即開(kāi)發(fā)一個(gè)Client  Wrapper,此wrapper提供了Producer常用的接口,且持有多個(gè)M-S組的ConnectionFactory,在通過(guò)底層通道發(fā)送消息之前,根據(jù)message中的某個(gè)property、或者指定的KEY,進(jìn)行hash計(jì)算,進(jìn)而選擇相應(yīng)的連接(或者Spring的包裝類),然后發(fā)送消息。這有點(diǎn)類似于基于客戶端的數(shù)據(jù)庫(kù)讀寫(xiě)分離的策略。

3)對(duì)于Consumers,則只需要配置多個(gè)ConnectionFactory即可。

4)經(jīng)過(guò)上述實(shí)踐,將消息sharding到多個(gè)M-S組,解決了消息發(fā)送效率的問(wèn)題,且邏輯集群可以進(jìn)行較大規(guī)模的擴(kuò)展。而且對(duì)Client是透明的。

5)如果你不想開(kāi)發(fā)shard-router層面,我們?nèi)匀豢梢曰趂ailover協(xié)議來(lái)實(shí)現(xiàn)“邏輯分布式”的消息散列存儲(chǔ),此時(shí)需要在failover協(xié)議中指明所有Groups的brokers節(jié)點(diǎn)列表,且randomize=true。這種用法,可以實(shí)現(xiàn)消息在多個(gè)Group上存儲(chǔ),唯一遺憾的地方時(shí),因?yàn)槿狈Α白詣?dòng)負(fù)載均衡策略”,可能導(dǎo)致消息分布不均。

配置如下:

failover:(tcp://G1.master,tcp://G1.slave,tcp://G2.master,tcp://G2.slave)?randomize=true   //randomize必須為true

“ActiveMQ架構(gòu)設(shè)計(jì)與實(shí)踐案例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI