ActiveMQ架構設計與實踐,需要一萬字

2021-01-11 51CTO

xjjdog以前寫過很多關於消息隊列的文章。今天介紹一下ActiveMQ。

ActiveMQ是最常用、特性最豐富的消息中間件,通常用於消息異步通信、削峰解耦等多種場景,是JMS規範的實現者之一。功能豐富到什麼程度呢?支持大部分消息協議,而且支持XA。

它也是比較古老的消息隊列,雖然最近新版本改名為Artemis,也不能去掉它身上滄桑的味道。就這麼一個重量級的東西,在很多公司尾大不掉,具體架構設計讓我為你娓娓道來。或許你應該從人性上,而不是技術上,來考慮一下它的存在性。

以下是正文。

1、架構設計概要

ActiveMQ提供兩種可供實施的架構模型:「M-S」和「network bridge」;其中「M-S」是HA方案,「網絡轉發橋」用於實現「分布式隊列」。

1.1、M-S

Master-Slave模型下,通常需要2+個ActiveMQ實例,任何時候只有一個實例為Master,向Client提供」生產」、「消費」服務,Slaves用於做backup或者等待Failover時角色接管。

M-S模型是最通用的架構模型,它提供了「高可用」特性,當Master失效後,Slaves之一提升為master繼續提供服務,且Failover之後消息仍然可以恢復。(根據底層存儲不同,有可能會有消息的丟失)。

有以下兩方面要點:

第一,M-S架構中,涉及到選舉問題,選舉的首要條件就是需要有「排它鎖」的支持。排它鎖,可以有共享文件鎖、JDBC資料庫排它鎖、JDBC鎖租約、zookeeper分布式鎖等方式實現。這取決你的底層存儲的機制。

第二,M-S架構中,消息存儲的機制有多種,「共享文件存儲」、「JDBC」存儲、「非共享存儲」等。不同存儲機制,各有優缺點。在使用的時候一定要權衡。

1.2、網絡轉發橋(network bridge)

無論如何,一組M-S所能承載的消息量、Client並發級別總是有限的,當我們的消息規模達到單機的上限時,就應該使用基於集群的方式,將消息、Client進行分布式和負載均衡。

ActiveMQ提供了「網絡轉發橋」模式,核心思想是:

1、集群中多個broker之間,通過「連接」互相通信,並將消息在多個Broker之間轉發和存儲,提供存儲層面的「負載均衡」。

2、根據Client的並發情況,對Client進行動態平衡,最終實現支持大規模生產者、消費者。

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

2、M-S架構設計詳解

2.1、非共享存儲模式

集群中有2+個ActiveMQ實例,每個實例單獨存儲數據,Master將消息保存在本地後,並將消息以異步的方式轉發給Slaves。

Master和slaves獨立部署,各自負責自己的存儲,Master與slaves之間通過「network connector」連接,通常是Master單向與slaves建立連接。master上接收到的消息將會全量轉發給slaves。

有下面幾個要點:

1)任何時候只有Master向Clients提供服務,slaves僅作backup。古老的影子節點方式。

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

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

4)當slaves需要提升為master時,應該確保此slaves的消息是最新的。

5)如果slaves離線,那麼在重啟slaves之前,還應該將master的數據手動同步給slaves。否則slave離線期間的數據,將不會在slaves上復現。

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

這種架構,是最原始的架構,易於實時,但是問題比較嚴重,缺乏Failover機制,消息的可靠性我們無法完全保障,因為master與slaves角色切換沒有仲裁者、或者說缺少分布式排它鎖機制。在Production環境中,不建議採用,如果你能容忍failover期間SLA水平降級的話,也可以作為備選。

2.2、共享文件存儲

即採用SAN(GFS)技術,基於網絡的全局共享文件系統模式(真是一個名次製造機器),這種架構簡單易用,但是可架構、可設計的能力較弱,在Production環境下酌情採用。

SAN存儲,可以參考GFS。其中master和slaves配置保持一致,每個broker都需要有唯一的brokerName;broker實例在啟動時首先通過SAN獲取文件系統的排它鎖,獲取lock的實例將成為master,其他brokers將等待lock、並間歇性的嘗試獲取鎖,slaves不提供Clients服務;因為brokers將數據寫入GFS,所以在failover之後,新的master獲取的數據視圖仍然與原master保持一致,畢竟GFS是全局的共享文件系統。

我們通常使用kahaDB作為存儲引擎,即使用日誌文件方式;kahaDB的存儲效率非常的高,TPS可以高達2W左右,是一種高效的、數據恢復能力強的存儲機制。

這種架構模式下,支持failover,當master失效後,Clients能夠通過failover協議與新的master重連,服務中斷時間很短。因為基於GFS存儲,所以數據總是保存在遠端共享存儲區域,所以不存在數據丟失的問題。

唯一的問題,就是GFS(SAN)的穩定性問題。這一點需要確定,SAN區域中的節點之間網絡通信必須穩定且高效。(自己搭建比如NFS服務,或者基於AWS EFS)。

這不過是把一個問題轉移到另外一個組件上而已。

2.3、基於JDBC共享存儲

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

但是JDBC存儲機制,性能實在是太低,與kahaDB這種基於日誌存儲層相比,性能相差近10倍左右。

Oh my god。不過在一些低並發,純粹解耦的場景是可以的。用在高並發網際網路就是找死(網際網路不一定意味著就是高並發的)。

如果你的業務需求,表明數據丟失是難以容忍的、且SLA水平很高很高,那麼JDBC或許是你最好的選擇。

既然JDBC資料庫為最終存儲層,那麼我們很多時候需要關注資料庫的可用性問題,比如資料庫基於M-S模式等;如果資料庫失效,將導致ActiveMQ集群不可用。

JDBC存儲面臨最大的問題就是「TPS」(吞吐能力),確實比kahaDB低數倍,如果你的業務存在高峰,「削峰」的策略可以首先將消息寫入本地文件(然後異步同步給AcitveMQ Broker)。

這個時候我總是有個疑問。直接使用資料庫就好了,您廢這麼大勁上個ActiveMQ又是何苦呢。可能是為了設計而設計吧。

3、network bridges模式架構

這種架構模式,主要是應對大規模Clients、高密度的消息增量的場景;它將以集群的模式,承載較大數據量的應用。

它有下面的要求和特點。

1)有大量Producers、Consumers客戶端接入。只所以如此,或許是因為消息通道(Topic,Queue)在水平擴張的方向上,已經沒有太大的拆分可能性。所以一股腦擠在一塊。

2)或許消息的增量,是很龐大的,特別是一些「非持久化消息」。我們寄希望於構建「分布式隊列」架構。也就是其他系統解決不了的問題,希望消息隊列能夠緩衝一下。

3)因為集群規模較大,我們可能允許集群某些節點短暫的離線,但數據恢復機制仍然需要提供,總體而言,集群仍然提供較高的可用性。

4)集群支持Clients的負載均衡,比如有多個producers時,這些producers會被動態的在多個brokers之間平衡。否則分配不均就會造成風險。

5)支持failover,即當某個broker失效時,Clients可以與其他brokers重連;當集群中有的新的brokers加入時,集群的拓撲也可以動態的通知給Clients。這個是運維人員最喜歡的,誰也不想大半夜起床搗鼓機器。

集群有多個子Groups構成,每個Group為M-S模式、共享存儲;多個Groups之間基於「network Connector」建立連接(masterslave協議),通常為雙向連接,所有的Groups之間彼此相連,Groups之間形成「訂閱」關係,比如G2在邏輯上為G1的訂閱者(訂閱的策略是根據各個Broker上消費者的Destination列表進行分類),消息的轉發原理也是基於此。

對於Client而言,仍然支持failover,failover協議中可以包含集群中「多數派」的節點地址。

對於Topic訂閱者的消息,將會在所有Group中複製存儲;對於Queue的消息,將會在brokers之間轉發,並最終到達Consumer所在的節點。

Producers和Consumers可以與任何Group中的Master建立連接並進行消息通信,當Brokers集群拓撲變化時、Producers或Consumers的個數變化時,將會動態平衡Clients的連接位置。Brokers之間通過「advisory」機制來同步Clients的連接信息,比如新的Consumers加入,Broker將會發送advisory消息(內部的通道)通知其他brokers。

集群模式提供了較好的可用性擔保能力,在某些特性上或許需要權衡,比如Queue消息的有序性將會打破,因為同一個Queue的多個Consumer可能位於不同的Group上,如果某個Group實現,那麼保存在其上的消息只有當其恢復後才能對Clients可見。

4、性能評估

綜上所述,在Production環境中,我們能夠真正意義上採用的架構,只有三種:

1)基於JDBC的共享資料庫模式:HA架構,單一Group,Group中包含一個master和任意多個slaves;所有Brokers之間通過遠端共享資料庫存取數據。對客戶端而言支持Failover協議。

2)基於Network Bridge構建分布式消息集群:Cluster架構,集群中有多個Group,每個Group均為M-S架構、基於共享存儲;對於Clients而言,支持負載均衡和Failover;消息從Producer出發,到達Broker節點,Broker根據「集群中Consumers分布」,將消息轉發給Consumers所在的Broker上,實現消息的按需流動。

3)基於Network Bridge的簡化改造:與2)類似,但是每個「Group」只有一個Broker節點,此Broker基於kahaDB本地文件存儲,即相對於2)Group缺少了HA特性;當Broker節點失效時,其上的消息將不可見、直到Broker恢復正常。這種簡化版的架構模式,通過增加機器的數量、細分消息的分布,來降低數據影響故障影響的規模,因為其基於kahaDB本地日誌存儲,所以性能很高。

4.1、共享JDBC測試結果

生產端配置。

Producer端(壓力輸出機器):數量:4臺       硬體配置:16Core、32G,雲主機       軟體配置:JDK 1.8,JVM 24G       並發與線程:32並發線程,連接池為128,發送文本消息,每個消息128個字符實體。消息:持久化,Queue,非事務 

Broker端配置。

Broker端(壓力承載)       數量:2臺       硬體配置:16Core、32G,雲主機       軟體配置:JDK 1.8,JVM 24G       架構模式:M-S模式,開啟異步轉發、關閉FlowControl,資料庫連接池為1024 

存儲層配置。

資料庫(存儲層)       數量:2臺       硬體配置:16Core、32G,SSD(IOPS 3000),雲主機       架構模式:M-S       資料庫:MySQL 

測試結果:

1、消息生產效率:1500 TPS

2、Broker負載情況:CPU 30%,內存使用率11%

3、MySQL負載情況:CPU 46%,IO_WAIT 25%

結論:

1、基於共享JDBC存儲架構,性能確實較低。

2、影響性能的關鍵點,就是資料庫的並發IO能力,當TPS在1800左右時,資料庫的磁碟(包括slave同步IO)已經出現較高的IO_WAIT。

3、通過升級磁碟、增加IOPS,可以有效提升TPS指標,建議同時提高CPU的個數。

打算採用資料庫來實現HA的同學們,你們看到這操蛋的TPS了麼?

4.2、基於非共享文件存儲的測試結果

測試單個ActiveMQ,基於kahaDB存儲,kahaDB分為兩種數據刷盤模式:

1)逐條消息刷盤

2)每隔一秒刷盤

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

壓力測試環境與1)保持一致,只是ActiveMQ的機器的磁碟更換為:SSD (600 IOPS)。

測試結果:

1)逐條刷新磁碟

TPS:660

Broker IO_WAIT:19%

2)每隔一秒刷新磁碟

TPS:9800

Broker IO_WAIT:1.6% (原則上優化磁碟和IOPS等,應該還能提升)

由此可見,基於日誌文件的存儲性能比JDBC高了接近5倍,其中逐條刷盤策略,消息的可靠性是最高的,但是性能卻低於JDBC。如果基於「每隔一秒刷盤」策略,在極端情況下,可能導致最近一秒的數據丟失。

還不錯,但離著kafka這樣的MQ還遠著呢。

4.3、基於轉發橋的測試結果

基於轉發橋的架構,實施成本較高,維護成本較高,架構複雜度也相對較大。本人根據實踐經驗,不推薦使用此模式。如果你希望嘗試,也無妨,畢竟它是ActiveMQ官方推薦的「分布式隊列實現機制」,從原理上它可以支持較大規模的消息存儲。

但是,我有更輕量級的,幹麼用你呢?

4.4、優秀實踐

所以本優秀實踐是在以上測試的基礎上得來的。

如果我們最終不得不面對「海量消息」的存儲,在按照業務進行隊列拆分之後,仍然需要面臨某個單純業務的消息量是「單個M-S架構」無法滿足的。而我們又不願意承擔Cluster模式複雜度所帶來的潛在問題,此時,可以採用比較通用的「邏輯分布式」機制。

1)構建多個M-S組,但是每個Group之間在物理上沒有關聯,即它們之間互不通信,且不共享存儲。

2)在Producer的客戶端,增加「router」層, 即開發一個Client Wrapper,此wrapper提供了Producer常用的接口,且持有多個M-S組的ConnectionFactory,在通過底層通道發送消息之前,根據message中的某個property、或者指定的KEY,進行hash計算,進而選擇相應的連接(或者Spring的包裝類),然後發送消息。這有點類似於基於客戶端的資料庫讀寫分離的策略。

3)對於Consumers,則只需要配置多個ConnectionFactory即可。

4)經過上述實踐,將消息sharding到多個M-S組,解決了消息發送效率的問題,且邏輯集群可以進行較大規模的擴展。而且對Client是透明的。

5)如果你不想開發shard-router層面,我們仍然可以基於failover協議來實現「邏輯分布式」的消息散列存儲,此時需要在failover協議中指明所有Groups的brokers節點列表,且randomize=true。這種用法,可以實現消息在多個Group上存儲,唯一遺憾的地方時,因為缺乏「自動負載均衡策略」,可能導致消息分布不均。

配置如下:

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

End

是的,我寫這一切的目的,就是為了讓你放棄ActiveMQ的。雖然我對它比較熟,但我知道誰更優秀。

希望改名後的Artemis,能夠給它帶來一點青春的氣息吧。

作者簡介:小姐姐味道 (xjjdog),一個不允許程式設計師走彎路的公眾號。聚焦基礎架構和Linux。十年架構,日百億流量,與你探討高並發世界,給你不一樣的味道。

【編輯推薦】

【責任編輯:

武曉燕

TEL:(010)68476606】

點讚 0

相關焦點

  • 理解RESTful API 架構設計規範與實踐
    摘要本文介紹了 REST 的由來,對 REST 的風格架構設計指導原則做了詳細的說明。同時舉例了過往開發中若干細節的考慮和實現方案。文字略長,預計需要10 ~ 20 分鐘讀完。也可以收藏起來,在需要的時候查閱。RESTful 架構是目前流行的一種網際網路應用架構。
  • 基於容器雲的微服務架構實踐
    【編者按】微服務架構的誕生和容器技術的流行,幾乎是同時發生的,這並非偶然,而是網際網路時代倒逼傳統技術和架構而產生的變革,而以Docker為代表的容器技術則為微服務理念提供了匹配的實現機制,本文作者從什麼是微服務切入,詳細的介紹了微服務架構的優勢,最後從自身實踐出發,給出了微服務架構的雲端實踐。
  • 華為企業架構實踐支撐業務變革
    研討會上,業界專家學者共同探討了EA(企業架構)在中國政府中應用的可行性。會中,華為企業業務中國區CTO王濤通過主題演講《華為企業架構實踐》,與在座專家分享了華為IT建設的歷程、IT治理體系、企業架構實踐等內容。王濤指出:華為IT建設的目標是支撐公司的價值主張以及戰略落地,華為不純粹追求IT自身的卓越,而是追求IT支撐公司運營的卓越。
  • 《RabbitMQ》如何保證消息的可靠性
    RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){ return new RabbitTemplate(connectionFactory); }}修改ymlspring: rabbitmq
  • 華為企業架構實踐支撐業務戰略與變革
    華為企業架構實踐支撐業務戰略與變革 2013年05月08日 10:08作者:Ben編輯:戴持文章出處:泡泡網原創     由北大信息化與信息管理研究中心主辦
  • 零度架構實踐系列視頻教程更新了
    第06期-規約模式最佳實踐(48分鐘)         規約模式用於定義可重用、可組合、有意義和可測試的過濾器,簡單地說,規約模式就是對查詢條件表達式用類的形式進行封裝,使用第三方開原始碼設計並構建自己的規約模式,抽象規約接口與基本實現,規約計算器,在倉儲模式中支持規約查詢
  • 什麼才是真正的架構設計?
    架構設計完全是為了業務,需求相對複雜.非功能性需求在整個系統佔據重要位置.系統生命周期長,有擴展性需求.系統基於組件或者集成的需要.業務流程再造的需要.二. 架構分層和分類架構分類可細分為業務架構、應用架構、技術架構, 代碼架構, 部署架構業務架構是戰略,應用架構是戰術,技術架構是裝備。
  • 從企業架構到信息化規劃,從現狀調研到架構設計的核心邏輯
    在這篇文章我不會詳細的去談當前主流的企業架構方法論理論框架和內容。而是根據多年IT諮詢實踐,將一些關鍵邏輯點和你分析。為什麼要談核心IT規劃和諮詢邏輯?可以毫不客氣的講,大部分的做IT規劃諮詢的人是不具備進行全局架構規劃諮詢能力的,這個一方面是需要你有大量業務和技術雙領域的實踐經驗積累,一方面是需要你真正做過大型的諮詢規劃項目並在這個過程中將實踐內容,各個架構之間輸出關係想清楚。系統學習下類似TOGAF課程當然有用,但是這不代表你具備了諮詢規劃能力。
  • 架構師必須知道的架構設計原則
    這些原則沉澱在架構師的腦海中,最終內化成他的 mindset,以潛意識方式影響和指導他的架構和設計工作。 一晃我在軟體研發行業工作十多個年頭了,前面大部分時間做架構設計和開發,現在轉型做研發管理。隨著時間的推移,很多技戰術細節性的東西 (工具,框架,程式語言) 在我腦海中漸漸模糊,但是一些平時學習積累起來,並且在實踐中加深體會的軟體架構設計和組織原則,這些原則性的東西卻絲毫沒有被時間衝淡,反而愈加清新。現在即使我不在一線開發,但這些沉澱下來的原則仍然潛移默化地影響我的日常管理和部分架構設計指導工作。我想有必要總結一下那些業界知名,給我留下深刻印象的軟體架構設計和組織原則,和大家一起分享。
  • 什麼是架構師?有何作用,成為一名架構師需要具備怎樣的能力?
    在軟體架構師領域中軟體開發設計的架構師,他們負責規劃程序的運行模式,層次結構,調用關係,規划具體的實現技術類型,甚至配合整個團隊做好軟體開發中的項目管理。摩託羅拉說副總裁 Toby Redshaw 說摩託羅拉的副總裁 Toby Redshaw 說,架構師是「IT 策略中的中樞」,而且這一角色對公司的影響確實非常大。
  • 架構設計:業務邏輯和技術分離
    硬是要給一個概述,我認為架構就是對系統中的實體以及實體之間的關系所進行的抽象描述。 架構始於建築,是因為人類發展(原始人自給自足住在樹上,也就不需要架構),分工協作的需要,將目標系統按某個原則進行切分,切分的原則,是要便於不同的角色進行並行工作。 2.
  • 「零信任」安全體系架構和實踐
    而Schema帳戶則類似於一個倉庫,數據和代碼只是需要一個倉庫存放而已,倉庫管理員不應該對放置在倉庫中的物資具有任意處置權。因此,以帳戶為基礎的安全體系無以為繼,需要把帳戶轉變為身份才可以在這種網絡中安全生存。  (2)現實生活中涉及巨大價值或巨大公共利益時,往往通過零信任體系而不是通過可信任體系來解決。數據的價值今非昔比,近幾年其價值在不斷放大,數據的託管性和多面性總會涉及眾多的公共利益。參照現實模型,零信任安全體系可以作為最恰當的數據安全體系架構。
  • 15 年架構設計經驗:我眼中的那些優秀架構師
    所以我面試的時候,就從他做過架構設計的項目出發,摘了幾個具體的點去深度溝通。 然而,當我真的圍繞「架構師」職責去考察時,卻發現,他對「架構師」的理解,還停留在接到需求後,依據產品設計給出實現的階段。對於接下來的模塊分解、代碼重構、技術選型、性能優化等方面,雖然他有所了解和接觸,但實在太過皮毛,缺乏體系化的理解。
  • 八種常見的業務設計和架構模型
    只要將企業架構與八種常見業務設計方法中的任何一種相關聯起來,你就可以更全面地了解企業體系結構實踐。 人們常常要求企業架構師確定計劃和項目的輕重緩急。要完成此任務,他們需要了解這些組織的戰略、策略和目標。這些信息往往很難收集,這可能是因為架構師從未意識到這些東西的存在,或者有時是因為它們根本就不存在。
  • 什麼是微內核架構設計?
    阿里妹導讀:作為一名Java程式設計師,相信同學們都聽說過微內核架構設計,也有自己的理解。那麼微內核是如何被提出來的?微內核在作業系統內核的設計中又有什麼作用?本文從插件化(Plug-in)架構的角度來詮釋微內核架構設計,通過微內核架構和微服務架構的對比,分享其對微服務設計的參考意義。
  • 為什麼說應用架構需要分類思維?
    阿里妹導讀:如何定義架構?應用架構的要素有哪些?什麼是應用架構中的分類思維?開源應用架構COLA的作者張建飛介紹他在COLA架構設計中的一些思想經驗,分享他的應用架構之道。文末福利:有哪些個性有趣的域名?
  • Redesign:Lofter的信息架構改版設計
    在做信息架構改版的時候分為前期調查,中期產出和後期評判。值得注意的是,在你開始著手做改版工作的時候很容易陷入其中而忘記思路,所以需要一個清晰的方法指導你完成整個改版設計而不迷失自己。除了上篇文章提到的在設計方案之前要做好需求分析,競品分析之外,還需要靈活運用各個研究方法,比較卡片分析法,用戶訪談,尼爾森十項原則等等,這些方法很好的幫助你完成你的設計,也讓你的設計更專業有理可循。什麼是信息架構?信息架構是對信息進行結構,組織方式以及歸類的設計,好讓使用者與用戶容易使用與理解的一項藝術與科學。
  • DDD到底適不適合微服務架構?
    從初期的單體架構,到豎井式架構、RPC架構,再到大放異彩的微服務架構,可以說架構演進,本質上就是基於業務,對現有架構的抽象過程。一名架構師,最怕缺少全局意識和長線思維。如果架構師設計架構的出發點,只是緩解燃眉之急,那麼在未來,這套系統的迭代會越來越困難,很可能陷入推翻、重建,再推翻、再重建的「鬼打牆」。
  • 測試-馬自達3 skyactive - x:未來的熱力發動機
    去年,我們在舊一代馬自達3的引擎蓋下測試了一款2.0 skyactive - x的原型車,這次是在它的最終版本中,我們在法蘭克福附近測試了它。這已經不是什麼秘密了:在馬自達,當需要開發符合新標準的發動機時,你首先要看看競爭對手在做什麼,以確定你不會做什麼。為了創意而創意?