您好,登錄后才能下訂單哦!
一、ActiveMQ的高可用性
ActiveMQ使用master-slave模式實現高可用性,提供兩種實現主從模式的配置:shared nothing、shared storage(a relational database and a shared file system)
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掛掉。
shared nothing master-slave模式的處理過程:當一個生產者發送一個持久化消息到master之后,master會復制該消息給slave,再返回接收應答給生產者,生產者才能發送下一個消息。
當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:
<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.
shared database master-slave
當一個ActiveMQ broker使用關系型數據庫時,它持有表的鎖以確保沒有其他broker同時訪問這個數據庫。多個broker同時運行并嘗試去訪問數據庫時,只有第一個broker會連接成功并拿到鎖,其他隨后到來的broker會一直poll直到它可以獲得鎖為止。這些處于polling狀態的broker,被視為slave,它們不會開啟任何傳輸連接或者網絡連接。
該配置中所有的broker可以使用同一份配置文件,這使得activemq啟動起來簡單得多。
shared file system master-slave
它建議使用 KahaDB 消息存儲,但是對于消息存儲使用底層的共享的文件系統。當KahaDB消息存儲啟動時,它將嘗試獲取文件鎖,以防止任何其他broker同時訪問基于文件的消息存儲。
二、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配置還有很多,不一一列舉了。
三、為大量并發應用程序部署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是流量分區的一個使用代表.
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。