天天看點

消息隊列RabbitMQ

消息隊列RabbitMQ

消息隊列

  

消息隊列的使用場景

 

解耦(為面向服務的架構(SOA)提供基本的最終一緻性實作)

場景說明:使用者下單後,訂單系統需要通知庫存系統。傳統的做法是,訂單系統調用庫存系統的接口。

消息隊列RabbitMQ

傳統模式的缺點:

假如庫存系統無法通路,則訂單減庫存将失敗,進而導緻訂單失敗

訂單系統與庫存系統耦合

引入消息隊列

消息隊列RabbitMQ

訂單系統:使用者下單後,訂單系統完成持久化處理,将消息寫入消息隊列,傳回使用者訂單下單成功

庫存系統:訂閱下單的消息,采用拉/推的方式,擷取下單資訊,庫存系統根據下單資訊,進行庫存操作

假如:在下單時庫存系統不能正常使用。也不影響正常下單,因為下單後,訂單系統寫入消息隊列就不再關心其他的後續操作了。實作訂單系統與庫存系統的應用解耦

為了保證庫存肯定有,可以将隊列大小設定成庫存數量,或者采用其他方式解決。

基于消息的模型,關心的是“通知”,而非“處理”。

短信、郵件通知、緩存重新整理等操作使用消息隊列進行通知。

消息隊列RabbitMQ

消息隊列和RPC的差別與比較:

RPC: 異步調用,及時獲得調用結果,具有強一緻性結果,關心業務調用處理結果。

消息隊列:兩次異步RPC調用,将調用内容在隊列中進行轉儲,并選擇合适的時機進行投遞(錯峰流控)

場景說明:使用者注冊後,需要發注冊郵件和注冊短信。傳統的做法有兩種 1.串行的方式;2.并行方式

擴充:

異步并發利器:實際項目中使用CompletionService提升系統性能的一次實踐

(1)串行方式:将注冊資訊寫入資料庫成功後,發送注冊郵件,再發送注冊短信。以上三個任務全部完成後,傳回給用戶端

消息隊列RabbitMQ

(2)并行方式:将注冊資訊寫入資料庫成功後,發送注冊郵件的同時,發送注冊短信。以上三個任務完成後,傳回給用戶端。與串行的差别是,并行的方式可以提高處理的時間

消息隊列RabbitMQ

引入消息隊列,将不是必須的業務邏輯,異步處理。改造後的架構如下:

消息隊列RabbitMQ

流量削峰也是消息隊列中的常用場景,一般在秒殺或團搶活動中使用廣泛

應用場景:系統其他時間A系統每秒請求量就100個,系統可以穩定運作。系統每天晚間八點有秒殺活動,每秒并發請求量增至1萬條,但是系統最大的處理能力隻能每秒處理1000個請求,于是系統崩潰,伺服器當機。

之前架構:大量使用者(100萬使用者)通過浏覽器在晚上八點高峰期同時參與秒殺活動。大量的請求湧入我們的系統中,高峰期達到每秒鐘5000個請求,大量的請求打到MySQL上,每秒鐘預計執行3000條SQL。但是一般的MySQL每秒鐘扛住2000個請求就不錯了,如果達到3000個請求的話可能MySQL直接就癱瘓了,進而系統無法被使用。但是高峰期過了之後,就成了低峰期,可能也就1萬使用者通路系統,每秒的請求數量也就50個左右,整個系統幾乎沒有任何壓力。

引入MQ:100萬使用者在高峰期的時候,每秒請求有5000個請求左右,将這5000請求寫入MQ裡面,系統A每秒最多隻能處理2000請求,因為MySQL每秒隻能處理2000個請求。系統A從MQ中慢慢拉取請求,每秒就拉取2000個請求,不要超過自己每秒能處理的請求數量即可。MQ,每秒5000個請求進來,結果隻有2000個請求出去,是以在秒殺期間(将近一小時)可能會有幾十萬或者幾百萬的請求積壓在MQ中。

關于流量削峰:秒殺系統流量削峰這事兒應該怎麼做?

這個短暫的高峰期積壓是沒問題的,因為高峰期過了之後,每秒就隻有50個請求進入MQ了,但是系統還是按照每秒2000個請求的速度在處理,是以說,隻要高峰期一過,系統就會快速将積壓的消息消費掉。我們在此計算一下,每秒在MQ積壓3000條消息,1分鐘會積壓18萬,1小時積壓1000萬條消息,高峰期過後,1個多小時就可以将積壓的1000萬消息消費掉。

消息隊列RabbitMQ

RabbitMQ 特點

生産者與消費者

 RabbitMQ 内部結構

消息隊列RabbitMQ

應用程式與代理伺服器的通信機制

AMQP消息路由:隊列、交換器和綁定

消息隊列RabbitMQ
消息隊列RabbitMQ
消息隊列RabbitMQ
消息隊列RabbitMQ

1、建立資訊。Publisher定義需要發送消息的結構和内容。

2、建立Conection和Channel。由Publisher和Consumer建立連接配接,連接配接到Broker的實體節點上,同時建立Channel。Channel是建立在Connection之上的,一個Connection可以建立多個Channel。Publisher連接配接Virtual Host 建立Channel,Consumer連接配接到相應的Queue上建立Channel。

3、聲明交換機和隊列。聲明一個消息交換機(Exchange)和隊列(Queue),并設定相關屬性。

4、發送消息。由Publisher發送消息到Broker中的Exchange中

5、路由轉發。RabbitMQ收到消息後,根據​​消息指定的Exchange(交換機) 來查找Binding(綁定) 然後根據規則(Routing Key)分發到不同的Queue。這裡就是說使用Routing Key在消息交換機(Exchange)和消息隊列(Queue)中建立好綁定關系,然後将消息發送到綁定的隊列中去。

6、消息接收。Consumer監聽相應的Queue,一旦Queue中有可以消費的消息,Queue就将消息發送給Consumer端。

7、消息确認。當Consumer完成某一條消息的處理之後,需要發送一條ACK消息給對應的Queue。

虛拟主機與隔離

每一個vhost本質都是一個mini版的Rabbitmq伺服器,擁有自己的隊列、交換器和綁定,還擁有自己的權限機制。

Vhost與Rabbit就像虛拟機與實體伺服器一樣。

它們通過在各自執行個體間提供邏輯分離,允許你為不同的應用程式安全保密運作資料。

這很有用,它能将同一個Rabbit的衆多客戶區分開來,又可以避免隊列和交換器的命名沖突。否則你可能不得不運作多個Rabbit,這将帶來更多管理問題,相反,你可以隻運作一個Rabbit,然後按需啟動或關閉vhost。

當你在Rabbit裡建立一個使用者,使用者通常會被指派給至少一個vhost,并且隻能通路被指派vhost内的隊列、交換器和綁定。Vhost之間是互相隔離的。

你将無法将vhost banana_tree上的交換器綁定到vhostoak_tree中的隊列去。這確定了安全性與可移植性。

注意:當你在RabbitMQ叢集上建立vhost,整個叢集上都會建立該vhost,vhost不僅消除了基礎架構中每一層運作一個RabbitMQ伺服器的需要,同樣避免了為每一層建立不同的叢集。

繼續閱讀