1. 程式人生 > >Rabbitmq原理和分析

Rabbitmq原理和分析

1、基本原理

MQ全稱為Message Queue,是一種分散式應用程式的的通訊方法,它是消費-生產者模型的一個典型的代表,producer往訊息佇列中不斷寫入訊息,而另一端consumer則可以讀取或者訂閱佇列中的訊息。

RabbitMQ是MQ產品的典型代表,是一款基於AMQP協議可複用的企業訊息系統。業務上,可以實現服務提供者和消費者之間的資料解耦,提供高可用性的訊息傳輸機制,在實際生產中應用相當廣泛。本文意在介紹Rabbitmq的基本原理,包括rabbitmq基本框架,概念,通訊過程等。

2、系統架構

Rabbitmq系統最核心的元件是Exchange和Queue,下圖是系統簡單的示意圖。Exchange和Queue是在rabbitmq server(又叫做broker)端,producer和consumer在應用端。

注意:生產者、消費者、中介軟體不必在一臺機器上,實際應用中也是絕大多數不在一起的。我們可以用一張圖表示RabbitMQ的構造:

Producer

訊息傳送者,在MQ中被稱為生產者(producer),一個傳送訊息的應用也被叫做生產者,用P表示。

Consumer

生產者“生產”出訊息後,最終由誰消費呢?等待接受訊息的應用程式,我們稱之為消費者(Consuming ),用C表示。

Queue

訊息只能儲存在佇列(queue)中。儘管訊息在rabbitMQ和應用程式間流通,但是佇列卻是存在於RabbitMQ內部。

一個佇列不受任何限制,它可以儲存你想要儲存的訊息量,它本質上是一個無限的緩衝區。

多個生產者可以向同一個佇列傳送訊息,多個消費者可以嘗試從同一個訊息佇列中接收資料。

一個佇列像下面這樣(上面是它的佇列名稱)

訊息佇列,提供了FIFO的處理機制,具有快取訊息的能力。Rabbitmq中,佇列訊息可以設定為持久化,臨時或者自動刪除。

1)、設定為持久化的佇列,queue中的訊息會在server本地硬碟儲存一份,防止系統crash,資料丟失。

2)、設定為臨時佇列,queue中的資料在系統重啟之後就會丟失。

3)、設定為自動刪除的佇列,當不存在使用者連線到server,佇列中的資料會被自動刪除。

Exchange

Exchange類似於資料通訊網路中的交換機,提供訊息路由策略。Rabbitmq中,producer不是通過通道直接將訊息傳送給queue,而是先發送給Exchange。一個Exchange可以和多個Queue進行繫結,producer在傳遞訊息的時候,會傳遞一個ROUTING_KEY,Exchange會根據這個ROUTING_KEY按照特定的路由演算法,將訊息路由給指定的queue。和Queue一樣,Exchange也可設定為持久化,臨時或者自動刪除。

Exchange有4種類型:direct(預設),fanout, topic, 和headers,不同型別的Exchange轉發訊息的策略有所區別:

1)、Direct 直接交換器,工作方式類似於單播,Exchange會將訊息傳送完全匹配ROUTING_KEY的Queue。

2)、fanout廣播是式交換器,不管訊息的ROUTING_KEY設定為什麼,Exchange都會將訊息轉發給所有繫結的Queue。

3)、topic主題交換器,工作方式類似於組播,Exchange會將訊息轉發和ROUTING_KEY匹配模式相同的所有佇列,比如,ROUTING_KEY為user.stock的Message會轉發給繫結匹配模式為 * .stock,user.stock, * . * 和#.user.stock.#的佇列。( * 表是匹配一個任意片語,#表示匹配0個或多個片語)。

4)、headers訊息體的header匹配(ignore)。

Binding

所謂繫結就是將一個特定的 Exchange 和一個特定的 Queue 繫結起來。Exchange 和Queue的繫結可以是多對多的關係。

virtual host

在Rabbitmq server上可以建立多個虛擬的message broker,又叫做virtual hosts (vhosts)。每一個vhost本質上是一個mini-rabbitmq server,分別管理各自的exchange和bindings。vhost相當於物理的server,可以為不同app提供邊界隔離,使得應用安全的執行在不同的vhost例項上,相互之間不會干擾。producer和consumer連線rabbit server需要指定一個vhost。

3、通訊過程

假設P1和C1註冊了相同的Broker,Exchange和Queue。P1傳送的訊息最終會被C1消費。基本的通訊流程大概如下所示:

1)、1生產訊息,傳送給伺服器端的。

2)、 ExchangeExchange收到訊息,根據ROUTINKEY,將訊息轉發給匹配的Queue1。

3)、 Queue1收到訊息,將訊息傳送給訂閱者C1。

4)、 C1收到訊息,傳送ACK給佇列確認收到訊息。

5)、 Queue1收到ACK,刪除佇列中快取的此條訊息。

Consumer收到訊息時需要顯式的向rabbit broker傳送basic.ack訊息或者consumer訂閱訊息時設定auto_ack引數為true。在通訊過程中,佇列對ACK的處理有以下幾種情況:

1)、如果consumer接收了訊息,傳送ack,rabbitmq會刪除佇列中這個訊息,傳送另一條訊息給consumer。

2)、 如果cosumer接受了訊息,但在傳送ack之前斷開連線,Rabbitmq會認為這條訊息沒有被deliver,在consumer在次連線的時候,這條訊息會被redeliver。

3)、 如果consumer接受了訊息,但是程式中有bug,忘記了ack,Rabbitmq不會重複傳送訊息。

4)、 Rabbitmq2.0.0和之後的版本支援consumer reject某條(類)訊息,可以通過設定requeue引數中的reject為true達到目地,那麼Rabbitmq將會把訊息傳送給下一個註冊的consumer。

4、應用場景

非同步處理

場景:使用者註冊後,傳送簡訊和郵箱通知等。

1)、序列邏輯耗時150s。

2)並行邏輯耗時100s。

3.mq訊息佇列處理耗時55s。

傳送註冊簡訊及郵箱通知不是必須的邏輯,所以放在mq中慢慢的消費,提高了系統的整體的效能。

應用解耦

場景:雙11購物節的時候,使用者下單後,訂單系統會及時通知庫存系統。

1)、傳統的做法:訂單系統介面呼叫庫存系統。

設想下,如果訂單系統正在呼叫庫存系統的時候,庫存系統發生崩潰了,那麼這個訂單就沒有成功,直接的造成了成交單的損失。

2)mq邏輯解耦。

訂單系統:使用者下單後,訂單系統完成持久化處理,將訊息寫入訊息佇列,返回使用者訂單下單成功。 

庫存系統:訂閱下單的訊息,獲取下單訊息,進行庫操作。 

這樣即使庫存系統發生崩潰,但是訂單的下單資訊仍然存在訊息佇列中,等庫存系統恢復正常後,繼續呼叫庫存介面,訊息不會丟失,保證了成交量。

併發削峰

針對高併發請求,比如雙11併發量超大的情況下,可以將使用者的下單訊息先存到訊息佇列中,這就極大的削弱了請求的併發量,然後慢慢消費訊息佇列中的訊息,很好的避免了卡著不動的局面,使用者體驗也會好很多。



作者:xiaonian0430
連結:https://www.jianshu.com/p/ff665a17473a
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。