日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

RabbitMQ 介紹

RabbitMQ 是一個由erlang語言編寫的、開源的、在AMQP基礎上完整的、可復用的企業消息系統。支持多種語言,包括JAVA、Python、ruby、php、C/C++等。

1.1.AMQP模型

AMQP:advanced message queuing protocol ,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,為面向消息的中間件設計。基于此協議的客戶端與消息中間件可傳遞的消息并不受客戶端/中間件不同產品、不同開發語言等條件的限制。

AMQP模型圖

 

RabbitMQ的開發應用

 

1.1.1.工作過程

發布者(Publisher)發布消息(Message),經由交換機(Exchange)。

交換機根據路由規則將收到的消息分發給與該交換機綁定的隊列(Queue)。

最后 AMQP 代理會將消息投遞給訂閱了此隊列的消費者,或者消費者按照需求自行獲取。

1、發布者、交換機、隊列、消費者都可以有多個。同時因為 AMQP 是一個網絡協議,所以這個過程中的發布者,消費者,消息代理 可以分別存在于不同的設備上。

2、發布者發布消息時可以給消息指定各種消息屬性(Message Meta-data)。有些屬性有可能會被消息代理(Brokers)使用,然而其他的屬性則是完全不透明的,它們只能被接收消息的應用所使用。

3、從安全角度考慮,網絡是不可靠的,又或是消費者在處理消息的過程中意外掛掉,這樣沒有處理成功的消息就會丟失。基于此原因,AMQP 模塊包含了一個消息確認(Message Acknowledgements)機制:當一個消息從隊列中投遞給消費者后,不會立即從隊列中刪除,直到它收到來自消費者的確認回執(Acknowledgement)后,才完全從隊列中刪除。

4、在某些情況下,例如當一個消息無法被成功路由時(無法從交換機分發到隊列),消息或許會被返回給發布者并被丟棄。或者,如果消息代理執行了延期操作,消息會被放入一個所謂的死信隊列中。此時,消息發布者可以選擇某些參數來處理這些特殊情況。

1.1.2.Excharge交換機

交換機是用來發送消息的 AMQP 實體。交換機拿到一個消息之后將它路由給一個或零個隊列。它使用哪種路由算法是由交換機類型和綁定(Bindings)規則所決定的。常見的交換機有如下幾種:

1. direct 直連交換機:Routing Key==Binding Key,嚴格匹配。

2. fanout 扇形交換機:把發送到該 Exchange 的消息路由到所有與它綁定的 Queue 中。

3. topic 主題交換機:Routing Key==Binding Key,模糊匹配。

4. headers 頭交換機:根據發送的消息內容中的 headers 屬性進行匹配。
具體有關這五種交換機的說明和用法,后續會有章節詳細介紹。

1.1.3.Queue隊列

AMQP 中的隊列(queue)跟其他消息隊列或任務隊列中的隊列是很相似的:它們存儲著即將被應用消費掉的消息。隊列跟交換機共享某些屬性,但是隊列也有一些另外的屬性。

· Durable(消息代理重啟后,隊列依舊存在)

· Exclusive(只被一個連接(connection)使用,而且當連接關閉后隊列即被刪除)

· Auto-delete(當最后一個消費者退訂后即被刪除)

· Arguments(一些消息代理用它來完成類似與 TTL 的某些額外功能)

1.2.rabbitmq和kafka對比

rabbitmq遵循AMQP協議,用在實時的對可靠性要求比較高的消息傳遞上。kafka主要用于處理活躍的流式數據,大數據量的數據處理上。主要體現在:

1.2.1.架構

1. rabbitmq:RabbitMQ遵循AMQP協議RabbitMQ的broker由Exchange,Binding,queue組成,其中exchange和binding組成了消息的路由鍵;客戶端Producer通過連接channel和server進行通信,Consumer從queue獲取消息進行消費(長連接,queue有消息會推送到consumer端,consumer循環從輸入流讀取數據)。rabbitMQ以broker為中心。

2. kafka:kafka遵從一般的MQ結構,producer,broker,consumer,以consumer為中心,消息的消費信息保存的客戶端consumer上,consumer根據消費的點,從broker上批量pull數據。

1.2.2.消息確認

1. rabbitmq:有消息確認機制。

2. kafka:無消息確認機制。

1.2.3.吞吐量

1. rabbitmq:rabbitMQ在吞吐量方面稍遜于kafka,他們的出發點不一樣,rabbitMQ支持對消息的可靠的傳遞,支持事務,不支持批量的操作;基于存儲的可靠性的要求存儲可以采用內存或者硬盤。

2. kafka:kafka具有高的吞吐量,內部采用消息的批量處理,zero-copy機制,數據的存儲和獲取是本地磁盤順序批量操作,具有O(1)的復雜度,消息處理的效率很高。
(備注:kafka零拷貝,通過sendfile方式。(1)普通數據讀取:磁盤->內核緩沖區(頁緩存 PageCache)->用戶緩沖區->內核緩沖區->網卡輸出;(2)kafka的數據讀取:磁盤->內核緩沖區(頁緩存 PageCache)->網卡輸出。

1.2.4.可用性

1. rabbitmq(1)普通集群:在多臺機器上啟動多個rabbitmq實例,每個機器啟動一個。但是你創建的queue,只會放在一個rabbtimq實例上,但是每個實例都同步queue的元數據。完了你消費的時候,實際上如果連接到了另外一個實例,那么那個實例會從queue所在實例上拉取數據過來。(2)鏡像集群:跟普通集群模式不一樣的是,你創建的queue,無論元數據還是queue里的消息都會存在于多個實例上,然后每次你寫消息到queue的時候,都會自動把消息到多個實例的queue里進行消息同步。這樣的話,好處在于,一個機器宕機了,沒事兒,別的機器都可以用。壞處在于,第一,這個性能開銷太大了,消息同步所有機器,導致網絡帶寬壓力和消耗很重。第二,這么玩兒,就沒有擴展性可言了,如果某個queue負載很重,你加機器,新增的機器也包含了這個queue的所有數據,并沒有辦法線性擴展你的queue

2. kafka:kafka是由多個broker組成,每個broker是一個節點;每創建一個topic,這個topic可以劃分為多個partition,每個partition可以存在于不同的broker上,每個partition就放一部分數據。這就是天然的分布式消息隊列,就是說一個topic的數據,是分散放在多個機器上的,每個機器就放一部分數據。每個partition的數據都會同步到其他機器上,形成自己的多個replica副本,然后所有replica會選舉一個leader出來,主從結構。

1.2.5.集群負載均衡

1. rabbitmq:rabbitMQ的負載均衡需要單獨的loadbalancer進行支持,如HAProxy和Keepalived等。

2. kafka:kafka采用zookeeper對集群中的broker、consumer進行管理,可以注冊topic到zookeeper上;通過zookeeper的協調機制,producer保存對應topic的broker信息,可以隨機或者輪詢發送到broker上;并且producer可以基于語義指定分片,消息發送到broker的某分片上。

2.結構

2.1.交換機模式

RabbitMQ常用的Exchange Type有fanout、direct、topic、headers這四種。

2.1.1.Direct Exchange

direct類型的Exchange路由規則很簡單,它會把消息路由到那些binding key與routing key完全匹配的Queue中。

2.1.2.Topic Exchange

前面講到direct類型的Exchange路由規則是完全匹配binding key與routing key,但這種嚴格的匹配方式在很多情況下不能滿足實際業務需求。topic類型的Exchange與direct類型的Exchage相似,也是將消息路由到binding key與routing key相匹配的Queue中,但支持模糊匹配:

· routing key為一個句點號“. ”分隔的字符串(我們將被句點號“. ”分隔開的每一段獨立的字符串稱為一個單詞),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”

· binding key與routing key一樣也是句點號“. ”分隔的字符串

· binding key中可以存在兩種特殊字符"*"與“#”,用于做模糊匹配,其中" * "用于匹配一個單詞,“#”用于匹配多個單詞(可以是零個)

2.1.3.Fanout Exchange

fanout類型的Exchange路由規則非常簡單,它會把所有發送到fanout Exchange的消息都會被轉發到與該Exchange 綁定(Binding)的所有Queue上。
Fanout Exchange 不需要處理RouteKey 。只需要簡單地將隊列綁定到exchange 上。這樣發送到exchange的消息都會被轉發到與該交換機綁定的所有隊列上。類似子網廣播,每臺子網內的主機都獲得了一份復制的消息。所以,Fanout Exchange 轉發消息是最快的。

2.1.4.Headers Exchange

headers類型的Exchange也不依賴于routing key與binding key的匹配規則來路由消息,而是根據發送的消息內容中的headers屬性進行匹配。
在綁定Queue與Exchange時指定一組鍵值對;當消息發送到Exchange時,RabbitMQ會取到該消息的headers(也是一個鍵值對的形式),對比其中的鍵值對是否完全匹配Queue與Exchange綁定時指定的鍵值對;如果完全匹配則消息會路由到該Queue,否則不會路由到該Queue。

2.1.5.Default Exchange 默認

嚴格來說,Default Exchange 并不應該和上面四個交換機在一起,因為它不屬于獨立的一種交換機類型,而是屬于Direct Exchange 直連交換機。

默認交換機(default exchange)實際上是一個由消息代理預先聲明好的沒有名字(名字為空字符串)的直連交換機(direct exchange)。

它有一個特殊的屬性使得它對于簡單應用特別有用處:那就是每個新建隊列(queue)都會自動綁定到默認交換機上,綁定的路由鍵(routing key)名稱與隊列名稱相同。

舉個例子:當你聲明了一個名為 “search-indexing-online” 的隊列,AMQP 代理會自動將其綁定到默認交換機上,綁定(binding)的路由鍵名稱也是為 “search-indexing-online”。所以當你希望將消息投遞給“search-indexing-online”的隊列時,指定投遞信息包括:交換機名稱為空字符串,路由鍵為“search-indexing-online”即可。

因此 direct exchange 中的 default exchange 用法,體現出了消息隊列的 point to point,感覺像是直接投遞消息給指定名字的隊列。

2.2.持久化

雖然我們要避免系統宕機,但是這種“不可抗力”總會有可能發生。rabbitmq如果宕機了,再啟動便是了,大不了有短暫時間不可用。但如果你啟動起來后,發現這個rabbitmq服務器像是被重置了,以前的exchange,queue和message數據都沒了,那就太令人崩潰了。不光業務系統因為無對應exchange和queue受影響,丟失的很多message數據更是致命的。所以如何保證rabbitmq的持久化,在服務使用前必須得考慮到位。

持久化可以提高RabbitMQ的可靠性,以防在異常情況(重啟、關閉、宕機等)下的數據丟失。RabbitMQ的持久化分為三個部分:交換器的持久化、隊列的持久化和消息的持久化。

2.2.1.exchange持久化

exchange交換器的持久化是在聲明交換器的時候,將durable設置為true。

如果交換器不設置持久化,那么在RabbitMQ交換器服務重啟之后,相關的交換器信息會丟失,不過消息不會丟失,但是不能將消息發送到這個交換器。

spring中創建exchange時,構造方法默認設置為持久化。

2.2.2.queue持久化

隊列的持久化在聲明隊列的時候,將durable設置為true。

如果隊列不設置持久化,那么RabbitMQ交換器服務重啟之后,相關的隊列信息會丟失,同時隊列中的消息也會丟失。

exchange和queue,如果一個是非持久化,另一個是持久化,中bind時會報錯。

spring中創建exchange時,構造方法默認設置為持久化。

2.2.3.message持久化

要確保消息不會丟失,除了設置隊列的持久化,還需要將消息設置為持久化。通過將消息的投遞模式(BasicProperties中的deliveryMode屬性)設置為2即可實現消息的持久化。

· 持久化的消息在到達隊列時就被寫入到磁盤,并且如果可以,持久化的消息也會在內存中保存一份備份,這樣可以提高一定的性能,只有在內存吃緊的時候才會從內存中清除。

· 非持久化的消息一般只保存在內存中,在內存吃緊的時候會被換入到磁盤中,以節省內存空間。

如果將所有的消息都進行持久化操作,這樣會影響RabbitMQ的性能。寫入磁盤的速度比寫入內存的速度慢很,所以要在可靠性和吞吐量之間做權衡。

在spring中,BasicProperties中的deliveryMode屬性,對應的是MessageProperties中的deliveryMode。平時使用的
RabbitTemplate.convertAndSend()方法默認設置為持久化,deliveryMode=2。如果需要設置非持久化發送消息,需要手動設置:

messageProperties.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);

2.2.4.完整方案

一、exchange、queue、message

要保證消息的持久化,在rabbitmq本身的結構上需要實現下面這些:

exchange交換機的durable設置為true。

queue隊列的durable設置為true。

message消息的投遞模式deliveryMode設置為2。

二、發布確認
前面是保證了消息在投遞到rabbitmq中,如何保證rabbit中消息的持久化。
那么還需要保證生產者能成功發布消息,如交換機名字寫錯了等等。可以在發布消息時設置投遞成功的回調,確定消息能成功投遞到目標隊列中。

三、接收確認
對于消費者來說,如果在訂閱消息的時候,將autoAck設置為true,那么消費者接收到消息后,還沒有處理,就出現了異常掛掉了,此時,隊列中已經將消息刪除,消費者不能夠在收到消息。

這種情況可以將autoAck設置為false,進行手動確認。

四、鏡像隊列集群
在持久化后的消息存入RabbitMQ之后,還需要一段時間才能存入磁盤。RabbitMQ并不會為每條消息都進行同步存盤,可能僅僅是保存到操作系統緩存之中而不是物理磁盤。如果在這段時間,服務器宕機或者重啟,消息還沒來得及保存到磁盤當中,從而丟失。對于這種情況,可以引入RabiitMQ鏡像隊列機制。

這里強調是鏡像隊列集群,而非普通集群。因為出于同步效率考慮,普通集群只會同步隊列的元數據,而不會同步隊列中的消息。只有升級成鏡像隊列集群后,才能也同步消息。

每個鏡像隊列由一個master和一個或多個mirrors組成。主節點位于一個通常稱為master的節點上。每個隊列都有自己的主節點。給定隊列的所有操作首先應用于隊列的主節點,然后傳播到鏡像。這包括隊列發布(enqueueing publishes)、向消費者傳遞消息、跟蹤消費者的確認等等。

發布到隊列的消息將復制到所有鏡像。不管消費者連接到哪個節點,都會連接到master,鏡像會刪除在master上已確認的消息。因此,隊列鏡像提高了可用性,但不會在節點之間分配負載。 如果承載隊列master的節點出現故障,則最舊的鏡像將升級為新的master,只要它已同步。根據隊列鏡像參數,也可以升級為同步的鏡像。

分享到:
標簽:RabbitMQ
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定